洛谷训练—交叉模拟

P1031 均分纸牌
有 N 堆纸牌,编号分别为 1,2,…, N。每堆上有若干张,但纸牌总数必为 N 的倍数。可以在任一堆上取若于张纸牌,然后移动。

移牌规则为:在编号为 1 堆上取的纸牌,只能移到编号为 2 的堆上;在编号为 N 的堆上取的纸牌,只能移到编号为 N-1 的堆上;其他堆上取的纸牌,可以移到相邻左边或右边的堆上。

现在要求找出一种移动方法,用最少的移动次数使每堆上纸牌数都一样多。

例如 N=4,4 堆纸牌数分别为:

①9②8③17④6

移动3次可达到目的:

从 ③ 取 4 张牌放到 ④ (9 8 13 10) -> 从 ③ 取 3 张牌放到 ②(9 11 10 10)-> 从 ② 取 1 张牌放到①(10 10 10 10)。

输入输出格式
输入格式:

键盘输入文件名。文件格式:

N(N 堆纸牌,1 <= N <= 100)

A1 A2 … An (N 堆纸牌,每堆纸牌初始数,l<= Ai <=10000)

输出格式:

输出至屏幕。格式为:

所有堆均达到相等时的最少移动次数。

输入输出样例
输入样例#1:

4
9 8 17 6

输出样例#1:

3

#include <iostream>
using namespace std;

int main()
{
	//先求出平均数,然后都减去平均数,
	//如果纸牌个数大于平均值,那么它就大于0,小于平均值,它就小于0
	//最后一摊一摊的向后推,推不完步数就加一
	//从左到右开始找,如果第i堆纸牌的个数ai不等于0,那么移动次数就+1
	int N;//N堆纸牌 
	int a[105],average=0;
	long long sum=0;
	int count=0;
	cin>>N;
	for( int i=0;i<N;i++)
	{
		cin>>a[i];
		sum+=a[i];
	}
	average=sum/N;
	for(int i=0;i<N;i++)
		a[i]-=average;
	for(int i=0;i<N;i++)
	{
		if(a[i]==0) continue;//说明与平均值相等,进入下一次循环
		a[i+1]+=a[i];//	//从左到右开始找,如果第i堆纸牌的个数ai不等于0,那么移动次数就+1
		 count++;
	}
		
	cout<<count;
	return 0;
}

P1086 花生采摘
题目描述
鲁宾逊先生有一只宠物猴,名叫多多。这天,他们两个正沿着乡间小路散步,突然发现路边的告示牌上贴着一张小小的纸条:“欢迎免费品尝我种的花生!――熊字”。

鲁宾逊先生和多多都很开心,因为花生正是他们的最爱。在告示牌背后,路边真的有一块花生田,花生植株整齐地排列成矩形网格(如图11)。有经验的多多一眼就能看出,每棵花生植株下的花生有多少。为了训练多多的算术,鲁宾逊先生说:“你先找出花生最多的植株,去采摘它的花生;然后再找出剩下的植株里花生最多的,去采摘它的花生;依此类推,不过你一定要在我限定的时间内回到路边。”
在这里插入图片描述
我们假定多多在每个单位时间内,可以做下列四件事情中的一件:

  1. 从路边跳到最靠近路边(即第一行)的某棵花生植株;

  2. 从一棵植株跳到前后左右与之相邻的另一棵植株;

  3. 采摘一棵植株下的花生;

  4. 从最靠近路边(即第一行)的某棵花生植株跳回路边。

现在给定一块花生田的大小和花生的分布,请问在限定时间内,多多最多可以采到多少个花生?注意可能只有部分植株下面长有花生,假设这些植株下的花生个数各不相同。
例如在图2所示的花生田里,只有位于(2, 5), (3, 7), (4, 2), (5, 4)的植株下长有花生,个数分别为13, 7, 15, 9。沿着图示的路线,多多在21个单位时间内,最多可以采到37个花生。
第一行包括三个整数,M, N和K,用空格隔开;表示花生田的大小为M * N(1 <= M, N <= 20),多多采花生的限定时间为K(0 <= K <= 1000)个单位时间。接下来的M行,每行包括N个非负整数,也用空格隔开;第i + 1行的第j个整数Pij(0 <= Pij <= 500)表示花生田里植株(i, j)下花生的数目,0表示该植株下没有花生。

输出格式:
输出文件peanuts.out包括一行,这一行只包含一个整数,即在限定时间内,多多最多可以采到花生的个数。

输入输出样例
输入样例#1: 复制
6 7 21
0 0 0 0 0 0 0
0 0 0 0 13 0 0
0 0 0 0 0 0 7
0 15 0 0 0 0 0
0 0 0 9 0 0 0
0 0 0 0 0 0 0
输出样例#1: 复制
37
输入样例#2: 复制
6 7 20
0 0 0 0 0 0 0
0 0 0 0 13 0 0
0 0 0 0 0 0 7
0 15 0 0 0 0 0
0 0 0 9 0 0 0
0 0 0 0 0 0 0
输出样例#2: 复制
28
说明
noip2004普及组第2题

#include <iostream>
#include <bits/stdc++.h>
using namespace std;

struct node{
	int x,y;//代表花生 的坐标
	int num;//代表花生的数量 
	 
}; 
node nuts[405];//M*N的最大值为20*20=400 
int cmp(node a,node b)
{
	return a.num>b.num;//降序排列 ,找花生较多的植株 
} 

int main()
{
	int M,N,K;//花生田的大小 ,K为花生采的限定时间 
	int plant[25][25];// 代表花生植株 
	int index=1;
	int tmp=0,dist,sum=0;//tmp用于记录剩下的时间,dist用于计算距离 
	//将二维数组里面的花生数量存储在nuts[]一维数组里面 
	cin>>M>>N>>K;
	for(int i=1;i<=M;i++)  //控制行数 
		for(int j=1;j<=N;j++)  //控制列数 
		{
			cin>>plant[i][j];	
			if(plant[i][j])
			{
				nuts[index].num=plant[i][j];
				nuts[index].y=i;//竖着的为y 
				nuts[index].x=j;//横着的为x 
				index++;	
			}	
				 
		}	
	sort(nuts+1,nuts+index,cmp);
	for(int i=1;i<index;i++)
	{
		if(i==1) dist=nuts[i].y;//i=1,说明靠近路边 ,如果i,j是从0开始,会出错,这里可以看出,如果i从01开始,那么对饮nuts[i].x就会有0,而计算计算距离时就会出错 
		else dist=abs(nuts[i].x-nuts[i-1].x)+abs(nuts[i].y-nuts[i-1].y);
		tmp = K-dist-1;//在K-dist的基础上再-1,是因为还要去掉采摘一棵植株上的花生的时间 
		if(tmp>=nuts[i].y)//保证能够跳回路边 
		{
			sum+=nuts[i].num;
			K=K-dist-1;
		}
		else break;
	}
	cout<<sum;
	
	return 0;
}

P1042 乒乓球
题目背景
国际乒联现在主席沙拉拉自从上任以来就立志于推行一系列改革,以推动乒乓球运动在全球的普及。其中1111分制改革引起了很大的争议,有一部分球员因为无法适应新规则只能选择退役。华华就是其中一位,他退役之后走上了乒乓球研究工作,意图弄明白1111分制和2121分制对选手的不同影响。在开展他的研究之前,他首先需要对他多年比赛的统计数据进行一些分析,所以需要你的帮忙。

题目描述
华华通过以下方式进行分析,首先将比赛每个球的胜负列成一张表,然后分别计算在1111分制和2121分制下,双方的比赛结果(截至记录末尾)。

比如现在有这么一份记录,(其中W表示华华获得一分,L表示华华对手获得一分):

WWWWWWWWWWWWWWWWWWWWWWLW

在1111分制下,此时比赛的结果是华华第一局11比0获胜,第二局11比0获胜,正在进行第三局,当前比分1比1。而在21分制下,此时比赛结果是华华第一局21比0获胜,正在进行第二局,比分2比1。如果一局比赛刚开始,则此时比分为0比0。直到分差大于或者等于2,才一局结束。

你的程序就是要对于一系列比赛信息的输入(WLWL形式),输出正确的结果。

输入输出格式
输入格式:
每个输入文件包含若干行字符串,字符串有大写的WW、LL和EE组成。其中EE表示比赛信息结束,程序应该忽略E之后的所有内容。

输出格式:
输出由两部分组成,每部分有若干行,每一行对应一局比赛的比分(按比赛信息输入顺序)。其中第一部分是11分制下的结果,第二部分是21分制下的结果,两部分之间由一个空行分隔。

输入输出样例
输入样例#1:
WWWWWWWWWWWWWWWWWWWW
WWLWE
输出样例#1:
11:0
11:0
1:1

21:0
2:1
说明
每行至多25个字母,最多有2500行

#include <iostream> 
#include <bits/stdc++.h>

using namespace std;

int main()
{
	string str,temp; 
	int flag=0;//用于控制输入,判断 是否到了E 
	int  W=0,L=0;//用于记录多少个W,用于记录多少个N 
	while(cin>>temp)
	{
		for(int i=0;i<temp.size();i++) 
		{
			if(temp[i]!='E'){
				str+=temp[i];
			}
			else{
				flag=1; 
				break;//当遇到E时停止 
			} 	
		}
		if(flag) break;
	}
	if(str.size()==0){
		cout<<"0:0"<<endl<<endl<<"0:0"<<endl;
	} 
	else{
		for(int i=0;i<str.size();i++){
			if(str[i]=='W') W++;
			else if(str[i]=='L') L++;
			if((W>=11||L>=11)&&abs(W-L)>=2){
				cout<<W<<":"<<L<<endl;
				W=0;L=0;
			}
		}
		cout<<W<<":"<<L<<endl<<endl;
		W=0;L=0;	
		for(int i=0;i<str.size();i++)
		{
			if(str[i]=='W') W++;
			else if(str[i]=='L') L++; 
			if((W>=21||L>=21)&&abs(W-L)>=2){
				cout<<W<<":"<<L<<endl;
				W=0;L=0;
			}
		}
		cout<<W<<":"<<L;
	}
	
	return 0;
}
 

P1098 字符串的展开
题目描述
在初赛普及组的“阅读程序写结果”的问题中,我们曾给出一个字符串展开的例子:如果在输入的字符串中,含有类似于“d-h”或者“4-8”的字串,我们就把它当作一种简写,输出时,用连续递增的字母或数字串替代其中的减号,即,将上面两个子串分别输出为“defgh”和“45678”。在本题中,我们通过增加一些参数的设置,使字符串的展开更为灵活。具体约定如下:

(1) 遇到下面的情况需要做字符串的展开:在输入的字符串中,出现了减号“-”,减号两侧同为小写字母或同为数字,且按照ASCII码的顺序,减号右边的字符严格大于左边的字符。

(2) 参数p1:展开方式。p1=1时,对于字母子串,填充小写字母;p1=2时,对于字母子串,填充大写字母。这两种情况下数字子串的填充方式相同。p1=3时,不论是字母子串还是数字字串,都用与要填充的字母个数相同的星号“*”来填充。

(3) 参数p2:填充字符的重复个数。p2=k表示同一个字符要连续填充k个。例如,当p2=3时,子串“d-h”应扩展为“deeefffgggh”。减号两边的字符不变。

(4) 参数p3:是否改为逆序:p3=1表示维持原来顺序,p3=2表示采用逆序输出,注意这时候仍然不包括减号两端的字符。例如当p1=1、p2=2、p3=2时,子串“d-h”应扩展为“dggffeeh”。

(5) 如果减号右边的字符恰好是左边字符的后继,只删除中间的减号,例如:“d-e”应输出为“de”,“3-4”应输出为“34”。如果减号右边的字符按照ASCII码的顺序小于或等于左边字符,输出时,要保留中间的减号,例如:“d-d”应输出为“d-d”,“3-1”应输出为“3-1”。

输入输出格式
输入格式:
输入文件expand.in包括两行:

第1行为用空格隔开的3个正整数,依次表示参数p1,p2,p3。

第2行为一行字符串,仅由数字、小写字母和减号“-”组成。行首和行末均无空格。

输出格式:
输出文件expand.out只有一行,为展开后的字符串。

输入输出样例
输入样例#1:
1 2 1
abcs-w1234-9s-4zz

输出样例#1:
abcsttuuvvw1234556677889s-4zz

输入样例#2:
2 3 2
a-d-d
输出样例#2:
aCCCBBBd-d
说明
40%的数据满足:字符串长度不超过5

100%的数据满足:1<=p1<=3,1<=p2<=8,1<=p3<=2。字符串长度不超过100

NOIP 2007 提高第二题

#include <iostream>
#include <bits/stdc++.h>
using namespace std;
int p1,p2,p3;
string getstring(char start,char end)
{
	string temp;
	//p2
	for(char c=start+1;c<=end-1;c++)
	{
		for(int i=0;i<p2;i++)
			temp+=c;//该字符要重复p2次 
	}
	//p3
	if(p3==2) //需要反转 
		reverse(temp.begin(),temp.end());
	//p1
	if(p1==1)//填充小写字母		
	{ 
		for(int i=0;temp[i];i++)
			temp[i]=tolower(temp[i]);		
	} 
	else if(p1==2)  //填充大写字母 
	{
		for(int i=0;temp[i];i++)
			temp[i]=toupper(temp[i]);
	}
	else if(p1==3) //全部替换为* 
	{
		for(int i=0;temp[i];i++)
		temp[i]='*';
	}	
	//同样,返回的中间字符串末尾先不连上end字符 
	temp=start+temp;
	return temp;
} 

int main()
{
	
	string str;//待输入的串 
	string ans;//展开的串 
	cin>>p1>>p2>>p3;
	cin>>str;
	for(int i=0;str[i];i++)
	{
		if(str[i]=='\n')
			continue;//遇到换行符就跳过 
		//遇到 -号就加上再跳过
		if(str[i]=='-'){  //??
			ans+='-';
			continue;
		}
		//当前下标为i的字符后面不是是减号 ,就加上这个字符  
		if(str[i+1]!='-') //str[i] 不是减号,str[i+1]也不是减号 
			ans+=str[i];
		//以下讨论情况是当前下标为i的字符后面是减号
		//连接都秉承着一个原则,符合的话都先连接减号和减号前面的字符或者只连接减号前面的字符,减号或者减号后面的字符自然会在下一次循环判断条件上连接
		else 
		{
			//如果减号前后两个字符相差1,就开始连接减号前面的字符		
			if(str[i+2]-str[i]==1)
			{
				ans+=str[i];	
			}	
			//如果后面的字符小于前面的字符或者两个字符不是同类的(即不是数字和数字或者不是字母和字母) 
			//这样就连接前面的字符和减号 
			else if(str[i+2]<=str[i]||(isalpha(str[i+2])!=isalpha(str[i])))
			{
				ans+=str[i];
				ans+=str[i+1];
			}
			//以上都不成立,就直接展开 
			else
			{
				ans+=getstring(str[i],str[i+2]);
			 } 
			i++;//防止下标错乱 
		} 
	}
	
	cout<<ans;
	
	
	return 0;
 } 

发布了81 篇原创文章 · 获赞 25 · 访问量 3万+

猜你喜欢

转载自blog.csdn.net/qq_43090158/article/details/95489345
今日推荐