[UVA 658] It's not a Bug, it's a Feature! (隐形图,最短路)

题意:

有n个bug,m种补补丁的方式,但是补补丁可能是有条件的,比如某个位置必须有bug,或某个位置必须没有bug,且补补丁也有可能在其他地方多生成bug。

'-'表示某位置有补丁,'+'表示某位置无补丁,'0'是占位符。

输入多组数据,每组数据输入:

m n

t a1 a2 ... an b1 b2 ... bn

...

t a1 a2 ... an b1 b2 ... bn

a表示补补丁需要的条件,b表示补补丁的操作。

Sample Input:

3 3
1 000 00-
1 00- 0-+
2 0-- -++
4 1
7 0-0+ ----
0 0

Sample Output:

Product 1
Fastest sequence takes 8 seconds.
Product 2
Bugs cannot be fixed.

思路:

既然n <= 20,那么很容易想到通过状态压缩表示补丁当前的状态。那么我们需要找出从2n到0的最短路径。于是想到跑一遍最短路。这道题其实是不用建边的,我们只需要每到一个状态跑m种选择,如果符合条件就将终点(处理后的状态)入栈就好了。

附上AC代码:

#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
#include<queue>
#define INF 1061109567
#define MAX (1 << 20) + 3
using namespace std;
// 大致思路:用二进制记录bug位置,每种情况为一个点,目标是从2^n走到0
// 建图不要先预处理,搜到每个点时再建边每个点判断可以到达的点
// 最后跑一遍最短路。
bool book[MAX] = {0};
int n,m,cost[150],dis[MAX];
int ch1[110][25],ch2[110][25],top1[110],top2[110];

struct node{
	int order,ti;
	bool operator < (const node & other)const{
		return ti > other.ti;
	}
};

priority_queue<node> q;
node newnode(int x,int y){
	node p;
	p.order = x;
	p.ti = y;
	return p;
}


int build(int i,int j){// i 状态 j 方案 
		bool fl = 1;
		for(int k=0; k<= top1[j]; k++){
			int r = (i >> (n - k - 1)) & 1;
			if(ch1[j][k] == '+' && r == 1)continue;
			if(ch1[j][k] == '-' && r == 0)continue;
			if(ch1[j][k] == '0')continue;
			fl = 0;
			break;
		}
		int to = i;
		if(!fl) return -1;
		for(int k=0; k<= top2[j]; k++){
			if(ch2[j][k] == '+')
				to |= 1 << (n - k - 1);
			if(ch2[j][k] == '-')//应把第n位修改为零 
				to &= (1 << n) - 1 - (1 << (n - k - 1));
		}
		if(i != to) return to;
}

void dijkstra(int o){
	node p;
	dis[o] = 0;
	q.push(newnode(o,0));
	while(!q.empty()){
		p = q.top();
		q.pop();
		if(book[p.order])continue;
		book[p.order] = 1;
		for(int j=1;j<=m;j++){
			int to = build(p.order,j);
			if(to != -1){
				if(p.ti + cost[j] < dis[to])
					dis[to] = p.ti + cost[j],
					q.push(newnode(to,dis[to]));
			}
		}		
	} 
}

int main(){
	int T = 0;
	while(scanf("%d%d",&n,&m) == 2){
	if(n == 0 && m == 0)break;
	memset(dis,0x3f,sizeof(dis));
	memset(book,0,sizeof(book));
	char c;
	
	for(int i=1; i<=m; i++){
		top1[i] = -1;
		scanf("%d ",&cost[i]);
		c = getchar();
		while(c == '0' || c == '+' || c == '-') 
		ch1[i][++top1[i]] = c,c = getchar();
		
		top2[i] = -1;
		c = getchar();
		while(c == '0' || c == '+' || c == '-') 
		ch2[i][++top2[i]] = c,c = getchar();
	}
	
	dijkstra((1<<n) - 1);
	if(dis[0] != INF)
		printf("Product %d\nFastest sequence takes %d seconds.\n\n",++T,dis[0]);
	else printf("Product %d\nBugs cannot be fixed.\n\n",++T);
}
	return 0;
} 
posted @ 2019-08-21 22:21  Cindy_Chan  阅读(187)  评论(0编辑  收藏  举报