动态规划状态压缩-poj1143
题目链接:http://poj.org/problem?id=1143
题目描述:
代码实现:
1 #include <iostream> 2 #include <string.h> 3 #include <math.h> 4 #include <algorithm> 5 #include <stdlib.h> 6 7 using namespace std; 8 int dp[1<<20]; 9 int n; 10 int a[25]; 11 int s[25]; 12 //这个函数是把这个二进制数列变成数字,就是将数列压缩成数字来 13 int getNum(int a[]) 14 { 15 int res=0; 16 for(int i=2;i<=20;i++) 17 { 18 if(a[i]) 19 res|=1; 20 res<<=1; 21 } 22 return res; 23 } 24 //dfs(a,2) 25 int dfs(int s[],int st) 26 { 27 int v[25]; 28 memcpy(v,s,25*sizeof(int));//memcpy的函数原型是void *memcpy(void *dest, const void *src, size_t n),其功能是从源src所指的内存地址的起始位置开始拷贝n个字节到目标dest所指的内存地址的起始位置中。 29 v[st]=0; 30 //把i的倍数,与之前选过的数字之和,都标记成0 31 for(int i=2;i+st<=20;i++) 32 { 33 if(!v[i]) 34 v[i+st]=0; 35 } 36 int ss=getNum(v); 37 //记忆化搜索,这里大幅度提高效率 38 if(dp[ss]!=0) 39 { 40 if(dp[ss]>0) 41 return 1; 42 else 43 return 0; 44 } 45 for(int i=2;i<=20;i++) 46 { 47 if(v[i]&&!dfs(v,i)) 48 { 49 dp[ss]=1; 50 return 1; 51 } 52 } 53 dp[ss]=-1; 54 return 0; 55 } 56 int main() 57 { 58 int ans[25]; 59 int b; 60 memset(dp,0,sizeof(dp)); 61 int cas=0; 62 while(scanf("%d",&n)!=EOF) 63 { 64 cas++; 65 memset(a,0,sizeof(a)); 66 if(n==0) 67 break; 68 for(int i=0;i<n;i++) 69 { 70 scanf("%d",&b); 71 a[b]=1; 72 } 73 int tot=0; 74 for(int i=2;i<=20;i++) 75 { 76 if(a[i]&&!dfs(a,i)) 77 ans[tot++]=i; 78 } 79 printf("Test Case #%d\n",cas); 80 if(tot==0) 81 { 82 printf("There's no winning move.\n"); 83 84 } 85 else 86 { 87 printf("The winning moves are: "); 88 for(int i=0;i<tot;i++) 89 { 90 if(i!=tot-1) 91 printf("%d ",ans[i]); 92 else 93 printf("%d\n",ans[i]); 94 } 95 } 96 printf("\n"); 97 } 98 return 0; 99 }