蓝桥杯 算法训练 合集1 C++

试题 算法训练 拿金币

问题描述   有一个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;

}
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值