试题 算法训练 拿金币
问题描述 有一个N x
N的方格,每一个格子都有一些金币,只要站在格子里就能拿到里面的金币。你站在最左上角的格子里,每次可以从一个格子走到它右边或下边的格子里。请问如何走才能拿到最多的金币。
输入格式 第一行输入一个正整数n。 以下n行描述该方格。金币数保证是不超过1000的正整数。 输出格式 最多能拿金币数量。
样例输入 3 1 3 3 2 2 2 3 1 2 样例输出 11 数据规模和约定 n<=1000
数据量很小,用了两个数组搞定
#include<iostream>
#include<algorithm>
using namespace std;
int n;
int x[1001][1001] = {0};
long long sum[1001][1001] = { 0 };
int main()
{
cin >> n;
int i, j;
for (i = 0; i < n; i++)
{
for (j = 0; j < n; j++)
{
cin >> x[i][j];
}
}
for (i = 0; i < n; i++)
{
for (j = 0; j < n; j++)
{
if (i == 0 && j == 0)
sum[0][0] = x[0][0];
else if (i == 0) sum[i][j] = sum[i][j - 1] + x[i][j];
else if (j == 0) sum[i][j] = sum[i - 1][j] + x[i][j];
else {
if (sum[i - 1][j] > sum[i][j - 1])
sum[i][j] = sum[i - 1][j] + x[i][j];
else
sum[i][j] = sum[i][j - 1] + x[i][j];
}
}
}
cout << sum[n-1][n-1];
return 0;
}
试题 算法训练 无聊的逗
问题描述
逗志芃在干了很多事情后终于闲下来了,然后就陷入了深深的无聊中。不过他想到了一个游戏来使他更无聊。他拿出n个木棍,然后选出其中一些粘成一根长的,然后再选一些粘成另一个长的,他想知道在两根一样长的情况下长度最长是多少。
输入格式
第一行一个数n,表示n个棍子。第二行n个数,每个数表示一根棍子的长度。
输出格式
一个数,最大的长度。
样例输入
4
1 2 3 1
样例输出
3
数据规模和约定
n<=15
借鉴了别人的思路,优化了函数,更易懂且减少参数。
这题直接暴力算就能过,毕竟n最高15,三次方也能接受。
如果n够大是不是应该用二分查找
#include<iostream>
#include<algorithm>
using namespace std;
int n,maxx=0;
int x[16];
void wow( int now, int a, int b)
{
if (a == b && a > maxx)
maxx = a;
if (now == n)
return;
wow(now + 1, a + x[now], b);
wow(now + 1, a, b + x[now]);
wow(now + 1, a, b);
}
int main()
{
int i;
cin >> n;
for (i = 0; i < n; i++)
cin >> x[i];
wow( 0, 0, 0);
cout << maxx;
return 0;
}
试题 算法训练 跳马
问题描述
一个8×8的棋盘上有一个马初始位置为(a,b),他想跳到(c,d),问是否可以?如果可以,最少要跳几步?
输入格式
一行四个数字a,b,c,d。
输出格式
如果跳不到,输出-1;否则输出最少跳到的步数。
样例输入
1 1 2 3
样例输出
1
数据规模和约定
0<a,b,c,d≤8且都是整数。
用数组确认是否经过过。
函数注意时刻终止,判断边界先if不符合就return,min不能取太大,大概估算即可。
#include<iostream>
#include<algorithm>
using namespace std;
int a, b, c, d;
int minn = 110;
void jump(int x, int y,int bu,int over[][10] )
{
if (bu > minn) return;
if (x >= 1 && x <= 8 && y >= 1 && y <= 8)
{
if (x == c && y == d)
{
if (bu < minn) minn = bu;
return;
}
if (over[x][y] == 0)
{
over[x][y] == 1;
jump(x - 2, y + 1, bu + 1, over);
jump(x - 1, y + 2, bu + 1, over);
jump(x + 2, y + 1, bu + 1, over);
jump(x + 1, y + 2, bu + 1, over);
jump(x - 2, y - 1, bu + 1, over);
jump(x - 1, y - 2, bu + 1, over);
jump(x + 2, y - 1, bu + 1, over);
jump(x + 1, y - 2, bu + 1, over);
}
else return;
}
else return;
}
int main()
{
int over[10][10] = { 0 };
cin >> a>> b>> c>>d;
jump(a,b,0,over);
if (minn != 110)
cout << minn;
else cout << -1;
}
试题 算法训练 kAc给糖果你吃
问题描述
kAc有n堆糖果,每堆有A[i]个。
kAc说你只能拿m次糖果,聪明的你当然想要拿最多的糖果来吃啦啦啦~
//第二天,kAc问你还想吃糖果么?(嘿嘿嘿)说着眼角路出奇怪的微笑…
输入格式
第一行两个数字n和m,第二行有n个数字A[i]。
输出格式
输出一行表示最多能拿几个糖果。
样例输入
2 2
1 2
样例输出
3
数据规模和约定
0<n≤1000
其余数字都是不超过1,000,000,000的非负整数。
最开始用C写的,现在我变秃了也变强了
C:
#include<stdio.h>
#include<stdlib.h>
struct node
{
int data;
node* next;
};
node* insert(node* head,int x)
{
node* f=head,*p;
if(head==NULL)
{
head=(node*)malloc(sizeof(node));
head->data=x;
head->next=NULL;
}
else
{
p=(node*)malloc(sizeof(node));
p->data=x;
p->next=NULL;
if(f->data<x)
{
p->next=head;
head=p;
}
else{
while(f->next!=NULL)
{
if(f->next->data<x)
{
p->next=f->next;
f->next=p;
break;
}
f=f->next;
}
if(f->next==NULL)
{
f->next=p;
}
}
}
return head;
}
int main()
{
node *head=NULL,*p;
int n,m;
long long sum=0;
int i,j,k;
scanf("%d%d",&n,&m);
for(i=0;i<n;i++)
{
scanf("%d",&k);
head=insert(head,k);
}
for(i=0;i<m;i++)
{
sum+=head->data;
p=head;
head=head->next;
free(p);
}
printf("%lld",sum);
system("pause");
return 0;
}
C++:
#include<iostream>
#include<algorithm>
using namespace std;
int n, m;
long long sum = 0;
long long x[1001];
int main()
{
int i;
cin >> n >> m;
for (i = 0; i < n; i++)
cin >> x[i];
sort(x, x + n,greater<long long>());
for (i = 0; i < m; i++)
sum += x[i];
cout << sum;
}
试题 算法训练 车的放置
问题描述
在一个n*n的棋盘中,每个格子中至多放置一个车,且要保证任何两个车都不能相互攻击,有多少中放法(车与车之间是没有差别的)
输入格式
包含一个正整数n
输出格式
一个整数,表示放置车的方法数
样例输入
2
样例输出
7
其实要是不考虑横坐标好像更快。。。
不过这个应该还挺好理解吧,这个位置能不能放,放了加一种可能,再撤回这一步往右继续判断。
PS:象棋走法我真的不懂啊,记录一下
马走日,车走直线,象飞田
#include<iostream>
#include<algorithm>
using namespace std;
int n;
int sum = 1;
int visited[10] = {0};
void dfs(int x, int y)
{
if (x >= n) return;
if (visited[y] == 1)
dfs(x+(y+1)/n, (y + 1)%n);
//else if (visited[y] == 1 && y == n)
//dfs(x + 1, 0);
if (visited[y] == 0)
{
sum++;
visited[y] = 1;
dfs(x + 1, 0);
visited[y] = 0;
dfs(x + (y + 1) / n, (y + 1) % n);
}
//else if (visited[y] == 0 && y == n)
}
int main()
{
cin >> n;
dfs(0, 0);
cout << sum;
}
试题 算法训练 最大分解
问题描述
给出一个正整数n,求一个和最大的序列a0,a1,a2,……,ap,满足n=a0>a1>a2>……>ap且ai+1是ai的约数,输出a1+a2+……+ap的最大值
输入格式
输入仅一行,包含一个正整数n
输出格式
一个正整数,表示最大的序列和,即a1+a2+……+ap的最大值
样例输入
10
样例输出
6
数据规模和约定
1<n<=10^6
样例说明
p=2
a0=10,a1=5,a2=1,6=5+1
先把可能的素数算出来,因数就是被整除后的得数
另,求素数的时候用素数求更快
#include<stdio.h>
#include<stdlib.h>
long long sum=0;
long long n;
int su[10001];
int suge=1;
void find()
{
int i,j;
for(i=3;i*i<=n;i++)
{
for(j=0;j<suge;j++)
{
if(i%su[j]==0)
break;
}
if(j==suge)
{
su[suge]=i;
suge++;
}
}
}
void con()
{
int i,j;
long long k=n;
while(k!=1)
{
for(i=0;i<suge;i++)
{
if(k%su[i]==0)
{
k/=su[i];
sum+=k;
break;
}
}
if(i==suge)
{
k=1;
sum+=k;
}
}
}
int main()
{
su[0]=2;
scanf("%lld",&n);
find();
con();
printf("%lld",sum);
/*
for(int i=0;i<suge;i++)
{
printf("%d ",su[i]);
}
*/
system("pause");
return 0;
}
试题 算法训练 士兵杀敌(二)
问题描述 南将军手下有N个士兵,分别编号1到N,这些士兵的杀敌数都是已知的。 小工是南将军手下的军师,南将军经常想知道第m号到第n号士兵的总杀敌数,请你帮助小工来回答南将军吧。
南将军的某次询问之后士兵i可能又杀敌q人,之后南将军再询问的时候,需要考虑到新增的杀敌数。 输入格式 多组测试数据,以EOF结尾;
每组第一行是两个整数N,M,其中N表示士兵的个数(1<N<1000000),M表示指令的条数。(1<M<100000)
随后的一行是N个整数,ai表示第i号士兵杀敌数目。(0<=ai<=100)
随后的M行每行是一条指令,这条指令包含了一个字符串和两个整数,首先是一个字符串,如果是字符串QUERY则表示南将军进行了查询操作,后面的两个整数m,n,表示查询的起始与终止士兵编号;如果是字符串ADD则后面跟的两个整数I,A(1<=I<=N,1<=A<=100),表示第I个士兵新增杀敌数为A.
输出格式 对于每次查询,输出一个整数R表示第m号士兵到第n号士兵的总杀敌数,每组输出占一行 样例输入 5 6 1 2 3 4 5
QUERY 1 3 ADD 1 2 QUERY 1 3 ADD 2 3 QUERY 1 2 QUERY 1 5 样例输出 6 8 8 20
不记录单人,记录和
多组测试数据,以EOF结尾;
while(scanf(“%d%d”,&n,&m)!=EOF)
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
long long arr[100001];
char list[5];
long long sum=0;
int n,m;
int main()
{
int i,j,k;
int a,b;
char t;
while(scanf("%d%d",&n,&m)!=EOF)
{
//scanf("%lld%lld",&n,&m);
for(i=1;i<=n;i++)
{
scanf("%d",&k);
if(i==1) arr[1]=k;
else arr[i]=arr[i-1]+k;
}
scanf("%c",&t);
for(i=0;i<m;i++)
{
scanf("%s%d%d",list,&a,&b);
if(strcmp(list,"QUERY")==0)
{
sum=0;
printf("%lld\n",arr[b]-arr[a-1]);
}
else
{
for(j=a;j<=n;j++)
arr[j]+=b;
}
}
}
system("pause");
return 0;
}