POJ 2908 Quantum
题意:从一种状态通过若干个需要能量操作转换成力另一种状态所需最少的能量。
一开始以为是位DP,后来发现位数(20)位太多,只能广度搜索,偷了一下懒,直接用优先队列,一开始没用pair,只保存状态,WA了3次。
pair的大小是先比较first再比较second
#include<cstdio> #include<cstring> #include<queue> #include<utility> #include<vector> using namespace std; typedef pair<int , int> Word ; int o[33],xo[33],an[33],c[33],n,m,l; bool b[1<<20]; priority_queue<Word, vector<Word>, greater<Word> > q; void Input() { int i,j; char str[22]; scanf("%d%d%d",&l,&n,&m); for(i=0;i<n;i++) { scanf("%s%d",str,&c[i]); for(j=o[i]=xo[i]=an[i]=0;j<l;j++) { o[i]<<=1; xo[i]<<=1; an[i]<<=1; an[i]++; switch(str[j]) { case 'S':o[i]++;break; case 'F':xo[i]++;break; case 'C':an[i]--;break; default:break; } } } } int Binary(char *s) { int i,k; for(i=k=0;i<l;i++) { k<<=1; if(s[i]=='1') k++; } return k; } int Search(int st,int ed) { int i,j,k; Word t; while(!q.empty()) q.pop(); q.push(make_pair(0,st)); for(;!q.empty();) { t=q.top(); q.pop(); j=t.second; if(b[j]) continue; if(j==ed) return t.first; b[j]=true; for(i=0;i<n;i++) { k=((j&an[i])|o[i])^xo[i]; if(!b[k]) q.push(make_pair(t.first+c[i],k)); } } return -1; } void Solve() { int i,k,st,ed; char str[22]; for(i=0;m--;i++) { if(i) putchar(' '); memset(b,false,sizeof(b)); scanf("%s",str); st=Binary(str); scanf("%s",str); ed=Binary(str); k=Search(st,ed); if(k>-1) printf("%d",k); else printf("NP"); } putchar('\n'); } int main() { int T; scanf("%d",&T); for(;T--;) { Input(); Solve(); } return 0; }