hdu 4317 Unfair Nim(状压DP)
来源:互联网 发布:通过ip地址查询域名 编辑:程序博客网 时间:2024/06/05 08:18
题意:给出n堆石子,两个人要进行nim游戏,后手要添加最少的石子使得自己必胜,求添加的石子数。
思路:根据nim游戏的原理知道,后手添加石子后,每一堆的石子数异或起来要等于0。本来想搞个贪心,后来发现不行,因为加石子可能产生进位问题,这样的话只能dp了。dp[i][j]表示前i位已经处理完,并且产生了进位j,此时要加的最小的数。j是一个二进制的数,这个数的第k位表示在第k堆是否由进位。那么就可以从低位向高位dp了,对于每个状态,计算一下加上进位后的数,枚举一下在这一位加的石子的状态,如果合法,就发生转移。写起来有些麻烦,要处理的东西不少,很多东西都要预处理出来,不然会超时,不过思路还是很清晰的。
代码:
#include<iostream>#include<cstdio>#include<cstring>#include<string>#include<algorithm>#include<map>#include<queue>#include<stack>#include<set>#include<cmath>#include<vector>#include<bitset>#define inf 0x3f3f3f3f#define Inf 0x3FFFFFFFFFFFFFFFLL#define eps 1e-6#define pi acos(-1.0)using namespace std;typedef long long ll;int dp[25][1<<10],val[25],msk[25],ok[1<<10],cost[25][1<<10],n;int res[1<<10][1<<10][2];inline int cal(int now,int add,int & next){ next = 0; for(int k = 0;k < 10;++k) { int x = (now>>k&1) + (add>>k&1); if(x == 2) { next |= (1<<k); if(now>>k&1) now ^= (1<<k); } else if(x == 1) { if(!(now>>k&1)) now ^= (1<<k); } } return now;}void Init(){ for(int i = 0;i < (1<<10);++i) { int x = i; ok[i] = 0; while(x) { ok[i]++; x = x&(x - 1); } ok[i] = (ok[i]&1)^1; } for(int i = 0;i < 20;++i) { for(int j = 0;j < (1<<10);++j) { cost[i][j] = 0; for(int k = 0;k < 10;++k) if(j & (1<<k)) cost[i][j] += 1<<i; } } for(int i = 0;i < (1<<10);++i) for(int j = 0;j < (1<<10);++j) { res[i][j][0] = cal(i,j,res[i][j][1]); }}int main(){// freopen("in.txt","r",stdin);// freopen("out.txt","w",stdout); Init(); while(~scanf("%d",&n)) { for(int i = 0;i < n;++i) scanf("%d",&val[i]); memset(msk,0,sizeof(msk)); for(int i = 0;i < 20;++i) { for(int j = 0;j < n;++j) msk[i] |= (val[j]>>i&1)<<j; } memset(dp,0x3f,sizeof(dp)); dp[0][0] = 0; for(int i = 0;i < 20;++i) { int now,next,x,y; for(int j = 0;j < (1<<n);++j) { if(dp[i][j] == inf) continue; now = msk[i];next = 0; next = res[now][j][1]; now =res[now][j][0];// now = cal(now,j,next); for(int k = 0;k < (1<<n);++k) { if(k & now & next) continue;// x = cal(now,k,y); x = res[now][k][0]; y = res[now][k][1]; if(!ok[x]) continue; dp[i+1][y|next] = min(dp[i+1][y|next],dp[i][j] + cost[i][k]); } } } int ans = inf; for(int i = 0;i < (1<<n);++i) { if(ok[i]) ans = min(ans,dp[20][i]); } if(ans == inf) puts("impossible"); else printf("%d\n",ans); } return 0;}
0 0
- hdu 4317 Unfair Nim(状压DP)
- hdu - 4317 - Unfair Nim - 状态dp
- hdu 4317 Unfair Nim
- hdu 4317 Unfair Nim(数位DP,4级)
- hdu 4317 Unfair Nim(状态压缩DP)——2012 Multi-University Training Contest 2
- HDU_4317 Unfair Nim 状态压缩dp
- hdu4317 Unfair Nim 二进制状态压缩
- hdu 1850 (nim games)
- Nim博弈(hdu 2176)
- HDU 4317 状压DP
- hdu 1907 && hdu 2509(Nim博弈)
- HDU 3032 - Nim or not Nim?(SG)
- HDU 3032 Nim or not Nim? (sg函数求解)
- HDU 3032 Nim or not Nim? (SG函数应用)
- HDU 3032 Nim or not Nim?(博弈 sg表)
- HDU 1536 S-Nim(组合游戏Nim)
- hdu 3032 Nim or not Nim? (sg函数规律)
- hdu 3032 Nim or not Nim? (一言不合就打表)
- Phalcon中使用UnitTest
- QT学习笔记_建立连接
- 九月英语总结——兴趣是最好的老师
- jsp内置对象part1
- Xcode设置项之Architectures和Valid Architectures
- hdu 4317 Unfair Nim(状压DP)
- 闲聊桌面应用开发[Win16->Win32->ATL/WTL/MFC->WinForm->WPF/Silverlight/WinRT]
- KinSlideshow参数设置说明
- vim/vim/vi常用命令
- Windows下安装mysql cluster
- SQL搜索近12个月的数据
- IOS开发 证书总结 转
- MongoDB集群——分片
- 如何在linux下,下载目录下所有的文本