https://vjudge.net/problem/UVA-658
思路:把每个bug的状态用2进制表示,把每个状态看成点,每个转化的过程看成边,由于补丁比较少,可以不建图直接暴力搜边就vans,dijkstra就行;
#include<iostream> #include<iomanip> #include<cstring> #include<sstream> #include<algorithm> #include<cstdio> #include<cmath> #include<stdlib.h> #include<string> #include<queue> #include<vector> #include<map> #include<set> #include<stack> //#include<bits/stdc++.h> #define _for(i,a,b) for(int i=a;i<=b;i++) using namespace std; typedef long long ll; const int mod =1e6+7; double esp=1e-6; int INF =0x3f3f3f3f; //const int inf = 1<<28; const int MAXN=200000+10; const int inf=0x3f3f3f3f; char be[110][25],af[110][25]; int vis[1<<20],d[1<<20],t[110],n,m; struct node { int bug,dist; bool operator < (const node &p)const { return dist>p.dist; } }; int dijkstar() { for(int i=0;i<(1<<n);i++) { d[i]=INF; vis[i]=0; } priority_queue<node> Q; Q.push((node){(1<<n)-1,0}); d[(1<<n)-1]=0; while(!Q.empty()) { node x=Q.top(); Q.pop(); if(x.bug==0)return x.dist; if(vis[x.bug])continue; vis[x.bug]=1; for(int i=0;i<m;i++) { bool f=1; for(int j=0;j<n;j++) { if(be[i][j]=='-'&&(x.bug&(1<<j))){f=0;break;} if(be[i][j]=='+'&&!(x.bug&(1<<j))){f=0;break;} } if(!f)continue; node next; next.bug=x.bug; next.dist=x.dist+t[i]; for(int j=0;j<n;j++) { if(af[i][j]=='+')next.bug |= (1<<j); if(af[i][j]=='-')next.bug &= ~(1<<j); } if(next.dist<d[next.bug]) { d[next.bug]=next.dist; Q.push(next); } } } return -1; } int main() { int Case=0; while(scanf("%d%d",&n,&m)&&n&&m) { for(int i=0;i<m;i++) { scanf("%d%s%s",&t[i],be[i],af[i]); } int ans=dijkstar(); printf("Product %d\n",++Case); if(ans<0)printf("Bugs cannot be fixed.\n\n"); else printf("Fastest sequence takes %d seconds.\n\n",ans); } return 0; }