阶梯博弈(poj 1704)

来源:互联网 发布:java 浏览器 编辑:程序博客网 时间:2024/05/12 17:50

觉得右边写的不错,简单粗暴,很好理解点击打开链接


题目:点击打开链接

这道题也是阶梯博弈,题意是在某些位置上棋子,然后两个人轮流向左边移动棋子,且棋子不能越过其他的棋子,也不能有多个棋子在同一个位置。

将两个相邻棋子之间的距离看成阶梯上的石子数。向左移动实际上就是向右下推石子,所以阶梯实际上是反向的:


这样与正着的阶梯不同的地方在于如果阶梯数是偶数的话,那么阶梯的奇偶性就会变化,如果是奇数则不变。

我的方法是从最后一个棋子与倒数第二个棋子之间的距离看成是第一级台阶上的石子数…………那么第一个棋子与第二个棋子的距离就是第一级台阶上的石子数。或者看了别人写的代码,他们是通过所给棋子的个数的奇偶性来判断,如果棋子数是奇数(阶梯数是偶数),那么就在0位置在加上数字0,这样原本奇数级阶梯就会变成偶数级阶梯,偶数级阶梯就会变成奇数级阶梯,奇偶性对调。如果棋子数是偶数(阶梯数时奇数)则不变。

其次这道题还要将所有的棋子个数排序,因为给数据的时候不一定是按照顺序给的。

然后,还有边界判断的问题,如果题目中没有告诉你位置1有棋子,那么就要在最前面的位置上加上数字0,因为最终的边界是在位置1,如果不加上0,最终边界就会变成最小的那个数字。 比如:输入 4 6 7 三个位置,如果不额外加上0,那么阶梯上的石子数就会变成1, 0 边界是4(棋子走到位置4就不走了)。而实际情况石子数应该是2, 1, 0(棋子走到位置1)

#include <stdio.h>#include <stdlib.h>#include <algorithm>using namespace std;int a[2000];int b[2000];int cmp(const void * a, const void * b){return *(int*)b - *(int*)a;}int main (void){int t;scanf("%d", &t);while(t --){int n, i;scanf("%d", &n);int f = 0, k = 0;for(i = 0; i < n; i++){scanf("%d", &a[i]);if(a[i] == 1)//判断边界 f = 1;}if(!f)a[n ++] = 0;//没有则补0 qsort(a, n ,sizeof(int), cmp);//从大到小排序int sum = 0;for(i = 0; i < n - 1 ; i ++)b[k ++] = a[i] - a[i + 1] - 1;for(i = 0; i < k; i += 2)sum ^= b[i];if(sum == 0)printf("Bob will win\n");elseprintf("Georgia will win\n");}return 0;}

蓝桥杯高僧斗法:

问题描述
  古时丧葬活动中经常请高僧做法事。仪式结束后,有时会有“高僧斗法”的趣味节目,以舒缓压抑的气氛。
  节目大略步骤为:先用粮食(一般是稻米)在地上“画”出若干级台阶(表示N级浮屠)。又有若干小和尚随机地“站”在某个台阶上。最高一级台阶必须站人,其它任意。(如图1所示)
  两位参加游戏的法师分别指挥某个小和尚向上走任意多级的台阶,但会被站在高级台阶上的小和尚阻挡,不能越过。两个小和尚也不能站在同一台阶,也不能向低级台阶移动。
  两法师轮流发出指令,最后所有小和尚必然会都挤在高段台阶,再也不能向上移动。轮到哪个法师指挥时无法继续移动,则游戏结束,该法师认输。
  对于已知的台阶数和小和尚的分布位置,请你计算先发指令的法师该如何决策才能保证胜出。
输入格式
  输入数据为一行用空格分开的N个整数,表示小和尚的位置。台阶序号从1算起,所以最后一个小和尚的位置即是台阶的总数。(N<100, 台阶总数<1000)
输出格式
  输出为一行用空格分开的两个整数: A B, 表示把A位置的小和尚移动到B位置。若有多个解,输出A值较小的解,若无解则输出-1。
样例输入
1 5 9
样例输出
1 4
样例输入
1 5 8 10
样例输出
1 3

同样的题型,只是这题要你输出能赢的走法。刚开始没有考虑到将两个和尚之间的距离增大所以只得了80分。

#include <stdio.h>#include <string.h>#include <stdlib.h>#include <ctype.h>char s[100000];int a[110], b[110];int cmp(const void * a, const void *b){return *(int *) a - *(int *)b;}int main (void){int i;gets(s);int len = strlen(s), k = 0, l = 0;for(i = 0; i < len; i++){if(isdigit(s[i]))k = k * 10 + (s[i] - 48);else{a[l ++] = k;k = 0;}}if(k != 0)a[l ++] = k;k = 0;qsort(a, l, sizeof(int), cmp);for(i = 0; i < l - 1; i++)b[k ++] = a[i + 1] - a[i] - 1;int sum = 0;for(i = 0; i < k; i += 2)sum ^= b[i];if(sum == 0)printf("-1\n");else{for(i = 0; i < k; i += 2){//只考虑奇数位置int temp = sum ^ b[i];//要将i+1个和尚和第i个和尚距离变为temp if(a[i + 1] - a[i] > temp){//如果第i+1个和尚和第i个和尚距离大于temp 将第i个往上移 printf("%d %d\n", a[i], a[i + 1] - temp - 1);break;}if(a[i + 2] > temp + a[i] + 1){//如果第i+1个和尚和第i个和尚距离小于temp且第i+2和尚与都i个和尚距离比temp大。 //将第i+1个往上移 printf("%d %d\n", a[i + 1], a[i] + temp + 1);break;}}}return 0;}


0 0
原创粉丝点击