正解应该是DLX。可惜不会,比赛中有神牛用dfs+剪枝过的,还有人用随机算法过的。各种Orz....
用了某大牛的dfs+剪枝,用二进制优化,好神奇、、、、
CODE:
/*状态压缩+迭代加深搜索*/ /*最小支配集*/ /*AC代码:7437ms*/ #include <iostream> #include <cstdio> #include <memory.h> #include <algorithm> #define ll(a) (a<<1) #define rr(a) (a<<1|1) #define ONE (__int64(1)) #define GOAL (__int64)((ONE<<(2*N))-1)//目标状态 using namespace std; int N,cas,pn,M,K,depth; __int64 st[100]; __int64 rest[100]; __int64 state; void Init() { int i,j,k,u,v,ith; scanf("%d",&N); state=0; pn=N<<1; for(i=0;i<pn;i++) { st[i]=rest[i]=0; //表示去了其中一个状态另一个就不用在被处理 st[i]|=(ONE<<i); st[i]|=(ONE<<(i^1)); } for(i=0;i<N;i++) { scanf("%d",&M); if(M==1) state|=(ONE<<rr(i));//表示已经处理 for(j=0;j<M;j++) { u=(ll(i))|j; scanf("%d",&K); { for(k=0;k<K;k++) { scanf("%d%d",&v,&ith); v=(ll(v))|ith; st[u]|=(ONE<<v); } } } } //预处理 rest[pn-1]=st[pn-1]; for(i=pn-2;i>=0;i--) rest[i]=st[i]|rest[i+1]; } bool dfs(__int64 state,int d,int p) { int i; if(d==depth) return state==GOAL; for(i=p;i<N;i++) { if((state|rest[ll(i)])!=GOAL) break;//剪枝 //if((state|st[ll(i)])==state) continue; if(dfs(state|st[ll(i)],d+1,i+1)) return true; if((state|rest[rr(i)])!=GOAL) break; if((state|st[rr(i)])==state) continue; if(dfs(state|st[rr(i)],d+1,i+1)) return true; } return false; } void Solve() { depth=1; //printf("@%I64d\n",GOAL); while(depth<N)//迭代加深 { if(dfs(state,0,0)) break; depth++; } printf("Case %d: %d\n",cas++,depth); } int main() { int T; cas=1; scanf("%d",&T); while(T--) { Init(); Solve(); } return 0; }