题意:发布的软件有n个bug,m个补丁。。每个补丁对软件的当前状态有一定的要求(某些bug必须存在,某些bug必须不存在,某些bug是否存在都可以,符合要求了才能打补丁),能修复一些bug,也可能引发一些新的bug。安装补丁需要一定的时间。问题是怎样打补丁,把全部的bug修复,花费的时间最少,或者无法完全修复bug。
思路:状态空间搜索,其实也是求图的最短路,毕竟放到了图论的习题。这题并不需要真正建图,对于每一个状态,扫描一下所有的补丁,如果能用,放到队列里往下搜就是了。
博主被这题坑死了。。无数次RE。。。把状态数组的大小开成了补丁数组的大小,一直没发现。。这题把字符串转成一个整数,用位运算能极大提高效率,不过我写的时候实现方法不是那么好,仅供参考。
#include <iostream>
#include <stdio.h>
#include <cmath>
#include <algorithm>
#include <iomanip>
#include <cstdlib>
#include <string>
#include <memory.h>
#include <vector>
#include <queue>
#include <stack>
#include <ctype.h>
#define INF 1000000000
using namespace std;
int n,m;//bug patche
char str1[110][30];
char str2[110][30];
int t[110];
int vis[1048580];
//1代表有bug,0代表没有bug
bool judge(int s,int k){
for(int i=0;i<n;i++){
if( !((s>>(n-i-1))%2) &&str1[k][i]=='+')return false;
if( ((s>>(n-i-1))%2) &&str1[k][i]=='-')return false;
}
return true;
}
int fix(int s,int k){
int fixint=0;
for(int i=0;i<n;i++){
if(str2[k][i]=='+'){
fixint++;
}else if( str2[k][i]=='0'&&(s>>(n-i-1))%2){
fixint++;
}
fixint=fixint<<1;
}
fixint=fixint>>1;
return fixint;
}
int main(){
int count=0;
while(cin>>n>>m){
if(n==0&&m==0)break;
count++;
for(int i=0;i<1048580;i++)vis[i]=INF;
for(int i=1;i<=m;i++){
cin>>t[i]>>str1[i]>>str2[i];
}
queue<int> que;
int s=(1<<n)-1;
que.push(s);
vis[s]=0;
bool flag=false;
while(!que.empty()){
int cur=que.front();
que.pop();
for(int i=1;i<=m;i++){
if(judge(cur,i)){
int tmp;
tmp=fix(cur,i);
if(vis[cur]+t[i]<vis[tmp]){
que.push(tmp);
vis[tmp]=vis[cur]+t[i];
}
}
}
}
printf("Product %d\n",count);
if(vis[0]!=INF){
printf("Fastest sequence takes %d seconds.\n",vis[0]);
}else{
cout<<"Bugs cannot be fixed."<<endl;
}
cout<<endl;
}
return 0;
}