一、题目概览
中文题目名称 | 连连看 | 取数 | 游戏 | 迎接仪式 |
英文题目名称 | card | cycle | game | welcome |
可执行文件名 | card | cycle | game | welcome |
输入文件名 | card.in | cycle.in | game.in | welcome.in |
输出文件名 | card.out | cycle.out | game.out | welcome.out |
每个测试点时限 | 1秒 | 1秒 | 1秒 | 1秒 |
测试点数目 | 10 | 10 | 10 | 10 |
每个测试点分值 | 10 | 10 | 10 | 10 |
比较方式 | 全文比较 | 全文比较 | 全文比较 | 全文比较 |
题目类型 | 传统 | 传统 | 传统 | 传统 |
二、提交源程序文件名
对于Pascal语言 | card.pas | cycle.pas | game.pas | welcome.pas |
对于C语言 | card.c | cycle.c | game.c | welcome.c |
对于C++语言 | card.cpp | cycle.cpp | game.cpp | welcome.cpp |
三、编译命令(不包含任何优化开关)
对于Pascal语言 | fpc game.pas | fpc hide.pas | fpc sign.pas | fpc chessman.pas |
对于C语言 | gcc –o game game.c | gcc –o hide hide.c | Gcc –o sign sign.c | gcc –o chessman chessman.c |
对于C++语言 | g++-o game game.cpp | g++-o hide hide.cpp | g++ -o sign sign.cpp | g++ -o chessman chessman.cpp |
四、运行内存限制
运行内存上限 | 256M | 256M | 256M | 256M |
注意事项:
1. 文件名(程序名和输入输出文件名)必须使用小写。
2. C/C++中函数main()的返回值类型必须是int,程序正常结束时的返回值必须是0。
3. 统一评测时采用的机器配置为:CPU 1.9GHz,内存512M,上述时限以此配置为准。
取数(cycle)
时间限制:1S
问题描述
有一个取数的游戏。初始时,给出一个环,环上的每条边上都有一个非负整数。这些整数中至少有一个0。然后,将一枚硬币放在环上的一个节点上。两个玩家就是以这个放硬币的节点为起点开始这个游戏,两人轮流取数,取数的规则如下:
(1)选择硬币左边或者右边的一条边,并且边上的数非0;
(2)将这条边上的数减至任意一个非负整数(至少要有所减小);
(3)将硬币移至边的另一端。
如果轮到一个玩家走,这时硬币左右两边的边上的数值都是0,那么这个玩家就输了。
如下图,描述的是Alice和Bob两人的对弈过程,其中黑色节点表示硬币所在节点。结果图(d)中,轮到Bob走时,硬币两边的边上都是0,所以Alcie获胜。
(a)Alice (b)Bob (c)Alice (d)Bob
现在,你的任务就是根据给出的环、边上的数值以及起点(硬币所在位置),判断先走方是否有必胜的策略。
【输入格式】
第一行一个整数N(N≤20),表示环上的节点数。
第二行N个数,数值不超过30,依次表示N条边上的数值。硬币的起始位置在第一条边与最后一条边之间的节点上。
【输出格式】
仅一行。若存在必胜策略,则输出“YES”,否则输出“NO”。
【样例】
cycle.in cycle.out
4 YES
2 5 3 0
cycle.in cycle.out
3 NO
0 0 0
最后取到数的人获胜
![](https://i-blog.csdnimg.cn/blog_migrate/8f900a89c6347c561fdf2122f13be562.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/961ddebeb323a10fe0623af514929fc1.gif)
/* 本题由于至少存在一个0,所以其实就是考虑一条链的情况 然后可以得出一个显然的结论,如果取一条边,那么一定要将它的权变为0,然后按链长的奇偶得出答案即可 */ #include<iostream> #include<cstdio> using namespace std; int a[100],n; int main(){ freopen("cycle.in","r",stdin); freopen("cycle.out","w",stdout); scanf("%d",&n); for(int i=1,j=n+1;i<=n;i++,j++)scanf("%d",&a[i]),a[j]=a[i]; int l=n,r=n+1; if(a[n]==0)l=n+1; if(a[n+1]==0)r=n; if(l>r){ printf("NO"); return 0; } while(a[r+1])r++; while(a[l-1])l--; if((n-l+1)%2==0&&(r-n)%2==0){ printf("NO"); return 0; } else printf("YES"); return 0; }
游戏(game)
问题描述
windy学会了一种游戏。
对于1到N这N个数字,都有唯一且不同的1到N的数字与之对应。
最开始windy把数字按顺序1,2,3,……,N写一排在纸上。
然后再在这一排下面写上它们对应的数字。
然后又在新的一排下面写上它们对应的数字。
如此反复,直到序列再次变为1,2,3,……,N。
如:
1 2 3 4 5 6
对应的关系为
1->2 2->3 3->1 4->5 5->4 6->6
windy的操作如下
1 2 3 4 5 6
2 3 1 5 4 6
3 1 2 4 5 6
1 2 3 5 4 6
2 3 1 4 5 6
3 1 2 5 4 6
1 2 3 4 5 6
这时,我们就有若干排1到N的排列,上例中有7排。
现在windy想知道,对于所有可能的对应关系,有多少种可能的排数。
输入
输入文件game.in包含一个整数,N。
输出
输出文件game.out包含一个整数,可能的排数。
样例输入
【输入样例一】
3
【输入样例二】
10
样例输出
【输出样例一】
3
【输出样例二】
16
数据规模和约定
30%的数据,满足 1 <= N <= 10 。
100%的数据,满足 1 <= N <= 1000 。 、
迎接仪式(welcome)
【问题描述】
LHX教主要来X市指导OI学习工作了。为了迎接教主,在一条道路旁,一群Orz教主er穿着文化衫站在道路两旁迎接教主,每件文化衫上都印着大字。一旁的Orzer依次摆出“欢迎欢迎欢迎欢迎……”的大字,但是领队突然发现,另一旁穿着“教”和“主”字文化衫的Orzer却不太和谐。
为了简单描述这个不和谐的队列,我们用“j”替代“教”,“z”替代“主”。而一个“j”与“z”组成的序列则可以描述当前的队列。为了让教主看得尽量舒服,你必须调整队列,使得“jz”子串尽量多。每次调整你可以交换任意位置上的两个人,也就是序列中任意位置上的两个字母。而因为教主马上就来了,时间仅够最多作K次调整(当然可以调整不满K次),所以这个问题交给了你。
【输入格式】
输入文件welcome.in的第1行包含2个正整数N与K,表示了序列长度与最多交换次数。
第2行包含了一个长度为N的字符串,字符串仅由字母“j”与字母“z”组成,描述了这个序列。
【输出格式】
输出文件welcome.out仅包括一个非负整数,为调整最多K次后最后最多能出现多少个“jz”子串。
【样例输入】
5 2
zzzjj
【样例输出】
2
【样例说明】
第1次交换位置1上的z和位置4上的j,变为jzzzj;
第2次交换位置4上的z和位置5上的j,变为jzzjz。
最后的串有2个“jz”子串。
【数据规模】
对于10%的数据,有N≤10;
对于30%的数据,有K≤10;
对于40%的数据,有N≤50;
对于100%的数据,有N≤500,K≤100
![](https://i-blog.csdnimg.cn/blog_migrate/8f900a89c6347c561fdf2122f13be562.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/961ddebeb323a10fe0623af514929fc1.gif)
/* dp[i][j][k]表示至第i位为止调换了j个‘j’和k个‘z’所得到的‘jz’串的最大个数, 每次只考虑s[i]和s[i-1]即可,只有'jz''jj''zz''zj'四种情况 */ #include<iostream> #include<cstring> #include<cstdio> using namespace std; int dp[501][101][101],n,m,ans; char s[501]; int main(){ freopen("welcome.in","r",stdin); freopen("welcome.out","w",stdout); scanf("%d%d",&n,&m); scanf("%s",s+1); for(int i=0;i<=n;i++) for(int j=0;j<=m;j++) for(int k=0;k<=m;k++) dp[i][j][k]=-0x7fffffff; dp[0][0][0]=dp[1][0][0]=0; if (s[1]=='j')dp[1][1][0]=0; else dp[1][0][1]=0; for(int i=2;i<=n;i++){ for(int j=0;j<=m;j++){ for(int k=0;k<=m;k++){ dp[i][j][k]=dp[i-1][j][k]; if(s[i-1]=='j'&&s[i]=='z')dp[i][j][k]=max(dp[i][j][k],dp[i-2][j][k]+1); if(s[i-1]=='j'&&s[i]=='j'&&j)dp[i][j][k]=max(dp[i][j][k],dp[i-2][j-1][k]+1); if(s[i-1]=='z'&&s[i]=='z'&&k)dp[i][j][k]=max(dp[i][j][k],dp[i-2][j][k-1]+1); if(s[i-1]=='z'&&s[i]=='j'&&j&&k)dp[i][j][k]=max(dp[i][j][k],dp[i-2][j-1][k-1]+1); if(j==k)ans=max(ans,dp[i][j][k]); } } } printf("%d",ans); }
连连看(card)
【问题描述】
有时大型游戏玩腻味了,小Z也会玩玩弱智级的小游戏,比如连连看。但小Z眼力不行,常常得分很低。于是,他找到了你,希望你能帮他找出一种获胜方案。
连连看的游戏规则很简单:玩家可以将 2 个相同图案的牌连接起来,连接线不多于 3 条线段,就可以成功将两个牌消除。将游戏界面上的牌全部消除掉,玩家就胜利了。
【输入】
输入文件card.in的第一行为两个正整数m和n,表示连连看游戏的矩阵大小。
接下来的m行,每行n个英文大写字母(为了计算方便,只用A~E五个字母),表示牌的种类,相同字母表示同种牌。
【输出】
输出文件card.out。
若能获胜,则输出共一行,包括m×n/2个英文大写字母,第i个字母表示第i次消除的牌的种类。若有多解,输出字典顺序最小的解。
若不能获胜,则输出共一行,包括字符串“Game over.”。
【输入输出样例1】
card.in | card.out |
2 1 A A | A |
【输入输出样例2】
Card.in | card.out |
2 1 A B | Game over. |
【限制】
100%的数据满足:m×n<=12