历届试题 约数倍数选卡片
问题描述
闲暇时,福尔摩斯和华生玩一个游戏:
在N张卡片上写有N个整数。两人轮流拿走一张卡片。要求下一个人拿的数字一定是前一个人拿的数字的约数或倍数。例如,某次福尔摩斯拿走的卡片上写着数字“6”,则接下来华生可以拿的数字包括:
1,2,3, 6,12,18,24 ....
当轮到某一方拿卡片时,没有满足要求的卡片可选,则该方为输方。
请你利用计算机的优势计算一下,在已知所有卡片上的数字和可选哪些数字的条件下,怎样选择才能保证必胜!
当选多个数字都可以必胜时,输出其中最小的数字。如果无论如何都会输,则输出-1。
在N张卡片上写有N个整数。两人轮流拿走一张卡片。要求下一个人拿的数字一定是前一个人拿的数字的约数或倍数。例如,某次福尔摩斯拿走的卡片上写着数字“6”,则接下来华生可以拿的数字包括:
1,2,3, 6,12,18,24 ....
当轮到某一方拿卡片时,没有满足要求的卡片可选,则该方为输方。
请你利用计算机的优势计算一下,在已知所有卡片上的数字和可选哪些数字的条件下,怎样选择才能保证必胜!
当选多个数字都可以必胜时,输出其中最小的数字。如果无论如何都会输,则输出-1。
输入格式
输入数据为2行。第一行是若干空格分开的整数(每个整数介于1~100间),表示当前剩余的所有卡片。
第二行也是若干空格分开的整数,表示可以选的数字。当然,第二行的数字必须完全包含在第一行的数字中。
第二行也是若干空格分开的整数,表示可以选的数字。当然,第二行的数字必须完全包含在第一行的数字中。
输出格式
程序则输出必胜的招法!!
样例输入
2 3 6
3 6
3 6
样例输出
3
样例输入
1 2 2 3 3 4 5
3 4 5
3 4 5
样例输出
4
思路:
思路:直接dfs搜索各种后继状态,抓住博弈的性质:对于必胜状态,必有一个后继状态是必败的,对于必败状态所有后继状态都是必胜的。假设当前选择是必胜态,那么后手的所有选择都必须是P态才行。
和nim游戏一个思想,把图画出来就好理解了,先手保证后手怎么选先手都有获胜的方式,后手保证先手至少先手有一种方式选择才可以保证先手胜,否则先手输
代码如下:
1 #include<bits/stdc++.h> 2 using namespace std; 3 int array[1000]; 4 int Aarray[1000]; 5 int array1[1000]; 6 int t1=0; 7 int t2=0; 8 int s=0; 9 int flag=1; 10 int DFS(int n) 11 { 12 int l; 13 if(s==0 || s%2==0){ 14 flag=1; 15 int a=1; 16 for(int i=t1-1;i>=0;i--){ 17 l=0; 18 if((n%array[i]==0 || array[i]%n==0) &&Aarray[i]==0 ){ 19 l++; 20 Aarray[i]=1; 21 s++; 22 a=DFS(array[i]); 23 s--; 24 Aarray[i]=0; 25 if(a==0){ flag=0; break;}//决策失败 26 } 27 } 28 if(a==0) return flag; 29 if(l==0){ 30 return 1; 31 } 32 }else{ 33 flag=0; 34 int a=0; 35 for(int i=t1-1;i>=0;i--){ 36 l=0; 37 if((n%array[i]==0 || array[i]%n==0) &&Aarray[i]==0){ 38 l++; 39 Aarray[i]=1; 40 s++; 41 a=DFS(array[i]); 42 s--; 43 Aarray[i]=0; 44 if(a==1){ flag=1; break;} 45 } 46 } 47 if(a==1) return flag; 48 if(l==0){ 49 return 0; 50 } 51 } 52 return flag; 53 } 54 int main() 55 { 56 //ios::sync_with_stdio(0),cin.tie(0); 57 memset(array1,0,sizeof(array1)); 58 memset(array,0,sizeof(array)); 59 memset(Aarray,0,sizeof(Aarray)); 60 int num; 61 char c; 62 while(true){ 63 cin >>num; 64 // scanf("%d",num); 65 c=getchar(); 66 array[t1++]=num; 67 if(c=='\n') break; 68 } 69 while(true){ 70 cin >> num; 71 //scanf("%d",num); 72 c=getchar(); 73 array1[t2++]=num; 74 if(c=='\n') break; 75 } 76 int m=0; 77 for(int i=0;i<t2;i++){ 78 79 int j; 80 for( j=0;j<t1;j++){ 81 if(array[j]==array1[i]){ 82 Aarray[j]=1; 83 break; 84 } 85 } 86 87 int aa= DFS(array1[i]); 88 Aarray[j]=0; 89 if(aa==1){ 90 cout << array1[i] << endl; 91 break; 92 }else{ 93 m++; 94 } 95 } 96 if(m==t2) cout << "-1" << endl; 97 return 0; 98 }
该代码第四第五组测试数据有点超时,网上有用vector降低时间复杂度的,今天状态不好,看以后再改进把。
作者:你的雷哥
本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须在文章页面给出原文连接,否则保留追究法律责任的权利。