UVa658 - It's not a Bug, it's a Feature!

        题意:发布的软件有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;
}


你可能感兴趣的:(图论,uva)