这道题算是一道到隐式搜索题,将每一个状态转化为二进制,但是如果用将每个状态建成一个图,空间需要太大,不可行,所以运用,priority_queue优化的dijkstra算法,只需对现有的边进行转换即可
注意一点,优先队列优先最大,但是题目是优先最小,因为这样才能最优
这个题建图很有特色
#include<stdio.h> #include<string.h> #include<stdlib.h> #include<iostream> #include<algorithm> #include<string> #include<queue> #include<map> #define MST(vis,x) memset(vis,x,sizeof(vis)) #define INF 0x3f3f3f3f #define maxn 20 #define maxm 110 using namespace std; int n,m; char before[maxm][maxn+5],after[maxm][maxn+5]; int tim[maxm]; int d[(1<<maxn)+5]; int judge[(1<<maxn)+5]; struct node { int bug; int dis; bool operator < (const node &x)const { return dis>x.dis; } }; int dij() { MST(d,INF); MST(judge,0); node temp,tt; temp.bug=(1<<n)-1; temp.dis=0; d[temp.bug]=0; priority_queue<node>q; q.push(temp); while(!q.empty()) { temp=q.top(); q.pop(); if(temp.bug==0)return temp.dis; if(judge[temp.bug])continue; judge[temp.bug]=1; for(int a=1;a<=m;a++) { int flag=0; for(int b=0;b<n;b++) { if(before[a][b]=='+'&&!(temp.bug&(1<<b))){flag=1;break;} if(before[a][b]=='-'&&(temp.bug&(1<<b))){flag=1;break;} } if(flag)continue; tt.bug=temp.bug; tt.dis=temp.dis+tim[a]; for(int b=0;b<n;b++) { if(after[a][b]=='-')tt.bug&=~(1<<b); else if(after[a][b]=='+')tt.bug|=(1<<b); } int &D=d[tt.bug]; if(tt.dis<D) { D=tt.dis; q.push(tt); } } } return -1; } int main() { int ans,t=1; while(scanf("%d%d",&n,&m)!=EOF) { if(!n&&!m)break; for(int a=1;a<=m;a++) scanf("%d%s%s",&tim[a],before[a],after[a]); ans=dij(); printf("Product %d\n",t++); if(ans<0) printf("Bugs cannot be fixed.\n\n"); else printf("Fastest sequence takes %d seconds.\n\n",ans); } return 0; }