问题 D: 小k的硬币问题
Posted dwvictor
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了问题 D: 小k的硬币问题相关的知识,希望对你有一定的参考价值。
题目描述
输入
接下来依次描述 T 组测试数据。对于每组测试数据:
第一行为两个整数 n,k,表示有n堆硬币,k为1则表示小k先拿,k为0则表示小k后拿。
接下来一行,有n个整数m1.....mn,表示每堆硬币的数量。
0<T<10,0<n<=1000,0<m<=10
输出
样例输入 Copy
4
1 1
10
5 0
9 9 3 5 6
6 0
1 1 1 1 1 1
2 1
10 1
样例输出 Copy
0 1 0 1
这道题要用到博弈论的思维来解答,先来分析每一堆硬币,数量为 1~10,当数量为 1 是,没法选择策略,只能拿 1 个,当数量为 2~5 时先选的人可以选择拿走 n-1 个,下 一堆硬币有优先选择权,也可以选择拿走 n 个,下一堆硬币后选,当数量为 6 时,只 有一种策略,就是拿走 5 个(因为拿走 5 个以下时,另一个人就能决定你下一堆硬币 的先后手,题目已经申明两个人都足够聪明),这是下一堆硬币先选,当数量为 7~10 的时候,可以选择拿走 n-6 个,此时对方只能拿走 5 个,然后自己拿走剩下的 1 个,
下一堆硬币后选,也可以直接拿走 5 个,让对方决定自己下堆硬币是先手还是后手。
因为考虑到一开始后手的人有一次一次性拿走一堆硬币的机会,所以以该角色进行倒 推(倒推的话,每个人在选择的时候都能看出自己之后怎么选才是最合适的),分为
4 个状态,该堆硬币有优先选择权,且有一次机会已经用过,2.该堆硬币没有优先选择 权,且一次机会已经用过,3.该堆硬币有优先选择权,且有一次机会,4.该堆硬币没有 优先选择权,且没有机会,保存每种状态下能拿到的最多的硬币数量。从后往前开始 逆推时,要考虑的如果有一次机会的话,可以通过这一次机会来改变自己下一堆硬币 的先后手,且如果是后手,对方只会选择让你拿到最少硬币的策略。当逆推结束是, 第二种状态能拿到的最多的硬币数量就是,后手这个角色能拿到的最多的硬币数量。
我的暴搜tle
1 #include<stdio.h> 2 #include<string.h> 3 int a[1010]; 4 int b[2]; 5 int m,n; 6 int sum = -1; 7 //a,b 8 //a = 0,c = 1; 9 void dfs(int i,int c,int d,int temp){ 10 // printf("%d ",c); 11 // printf("%d ",d); 12 // printf("%d ",a[i]); 13 //printf("%d ",temp); 14 if(i==m+1) 15 { 16 if(n==0){ 17 18 if(c<d){ 19 // printf("%d %d",c,d); 20 sum = 1; 21 // i--; 22 return ; 23 } 24 else if(sum!=1&&c == d) 25 { 26 sum = 0; 27 // i-- ; 28 return ; 29 } 30 // i--; 31 return ; 32 } 33 else 34 { 35 if(c>d){ 36 // printf("%d %d",c,d); 37 sum = 1; 38 // i--; 39 return ; 40 } 41 else if(sum!=1&&c == d) 42 { 43 sum = 0; 44 // i-- ; 45 return ; 46 } 47 // i--; 48 return ; 49 } 50 51 } 52 53 if(a[i]==1) 54 { 55 //temp 0 dy c dy !k 56 if(temp == 0){ 57 58 dfs(++i,c++,d,1-temp),i--,c--,1-temp; 59 return; 60 } 61 else{ 62 63 dfs(++i,c,d++,1-temp),i--,c,d--,1-temp; 64 return; 65 } 66 //d[n]++,n = 1-n; 67 } 68 69 else if(2<=a[i]&&a[i]<=5){ 70 //1 71 // d[n]+=a[i]-1,d[1-n] +=1; 72 if(temp==0) //a+=a[i] - 1 d += 1{ 73 { 74 75 dfs(++i,c+=a[i] - 1, d += 1,temp),i--,c-=a[i] - 1, d -= 1; 76 //2 77 dfs(++i,c+=a[i],d,1-temp),i--,c-=a[i],d,1-temp; 78 // d[n]+=a[i],n = 1-n; 79 return; 80 } 81 else{ 82 dfs(++i,d+=a[i] - 1, c += 1,temp),i--,d-=a[i] - 1, c -= 1; 83 //2 84 dfs(++i,d+=a[i],c,1-temp),i--,d-=a[i],c,1-temp; 85 return; 86 } 87 } 88 else if(a[i]==6){ 89 // d[n] += 5; 90 // d[1-n]++; 91 if(temp == 0){ 92 dfs(++i,c+=5,d++,temp),i--,c-=5,d--; 93 return; 94 } 95 else{ 96 97 dfs(++i,d+=5,c++,temp),i--,d-=5,c--; 98 // i-- 99 return; 100 } 101 } 102 else if(a[i]>=7&&a[i]<=10){ 103 //1 104 if(temp ==0){ 105 106 dfs(++i,c+=a[i]-6+1,d+=5,1-temp),i--,c-=a[i]-6+1,d-=5,1-temp; 107 //d[n] += a[i] - 6,d[1-n] += 5,d[n]+=1,n = 1-n; 108 //2 109 // i--; 110 dfs(++i,c+=5,d+=a[i]-5,temp),i--,c-=5,d-=a[i]-5; 111 // i--; 112 //d[n] += 5; 113 //2.1 114 // d[1-n] +=a[i] - 5; 115 dfs(++i,c+=6,d+=a[i]-6,1-temp),i--,c-=6,d-=a[i]-6,1-temp; 116 // i--; 117 return; 118 } 119 else if(temp ==1){ 120 121 dfs(++i,d+=a[i]-6+1,c+=5,1-temp),i--,d-=a[i]-6+1,c-=5,1-temp; 122 // i--; 123 // printf("%d",d); 124 //d[n] += a[i] - 6,d[1-n] += 5,d[n]+=1,n = 1-n; 125 //2 126 dfs(++i,d+=5,c+=a[i]-5,temp),i--,d-=5,c-=a[i]-5; 127 // i--; 128 //d[n] += 5; 129 //2.1 130 // d[1-n] +=a[i] - 5; 131 if(m!=1) 132 dfs(++i,d+=6,c+=a[i]-6,1-temp),i--,d-=6,c-=a[i]-6,1-temp; 133 //dfs(++i,d+=6,c+=a[i]-6,1-temp),i--,d-=6,c-=a[i]-6,1-temp; 134 // i--; 135 return; 136 } 137 //2.2 138 // d[1-n] +=a[i] - 5 -1,d[n]++,n = 1-n; 139 } 140 141 } 142 int main(){ 143 int t; 144 145 146 scanf("%d",&t); 147 while(t--){ 148 //分别为堆数 149 memset(a,0,sizeof(a)); 150 sum = -1; 151 scanf("%d%d",&m,&n); 152 for(int i = 1;i<=m;i++){ 153 scanf("%d",&a[i]); 154 } 155 int temp = n; 156 dfs(1,0,0,temp); 157 // for(int i = 1;i<=m;i++){ 158 // if(a[i]==1) 159 // d[n]++,n = 1-n; 160 // else if(2<=a[i]&&a[i]<=5){ 161 // //1 162 // b[n]+=a[i]-1,b[1-n] +=1; 163 // //2 164 // b[n]+=a[i],n = 1-n; 165 // 166 // } 167 // else if(a[i]==6){ 168 // b[n] += 5; 169 // b[1-n]++; 170 // 171 // } 172 // else if(a[i]>=7&&a[i]<=10){ 173 // //1 174 // b[n] += a[i] - 6,b[1-n] += 5,b[n]+=1,n = 1-n; 175 // //2 176 // b[n] += 5; 177 // //2.1 178 // b[1-n] +=a[i] - 5; 179 // //2.2 180 // b[1-n] +=a[i] - 5 -1,b[n]++,n = 1-n; 181 // } 182 // 183 // } 184 if(sum){ 185 printf("1 "); 186 } 187 else if(sum==0) 188 { 189 printf("0 "); 190 } 191 else if(sum ==-1) 192 { 193 printf("-1 "); 194 } 195 } 196 }
以上是关于问题 D: 小k的硬币问题的主要内容,如果未能解决你的问题,请参考以下文章