uva 658 It's not a Bug, it's a Feature! 最短路dijstra

题意:给定n个bug(n个位置全是bug),m个补丁。对于每个补丁的功能描叙有规定:补丁花费的时间   打补丁前的状态  打补丁后的状态。其中“状态”用一个字符串描叙,第I位代表第I个bug的状态。

前:0代表有无对补丁无影响,-这个位置不能有bug,+这个位置必须有bug。

后:0代表补丁对这个位置不起作用,原来是怎样,打补丁后还是怎样。-:该位置的bug被修补,如果没有bug不起作用,+:该补丁在这个位置处引入bug。

每个补丁可以重复使用,求用最短的时间,将所有bug修复,如果不能做到,输出特定字符串。

思路:bug数不超过20个,用整型可以存储20个位,考虑用1代表这个位置有bug,0表示无bug。开始的状态是(1<<n)-1,所有位均为1,视作一个顶点。则终点是全0,即0。为了方便处理,将输入的补丁倒序。对于每个状态,试探所有补丁,满足条件则转移,因为打了补丁可能回到之前的状态,不能用动态规划。用dijstra求最短路即可。

看错条件,将n看作1=<n<=10,找了很久才发现= =。结果是疯狂re。很经典的一道题。

#include<cstdio>
#include<cstring>
#include<queue>
#include<algorithm>
const int maxm = 110;
using namespace std;
struct Pt
{
	char pre[maxm];
	char num[maxm];
	int t;
}pt[maxm];
struct node
{
	int x,d;
	bool operator < (const node &b)const
	{
		return d>b.d;
	}
};
int d[1<<22],vis[1<<22];
int n,m;//the number of bugs and patches 1=<n<=20
int dijstra(int s)
{
	priority_queue<node,vector<node> > q;
	for(int i=0;i<(1<<22);i++)d[i]=1<<30;
	d[s]=0;
	q.push(node{s,0});
	int u;
	memset(vis,0,sizeof(vis));
while(!q.empty())
{
	node a=q.top();q.pop();
	u=a.x;
	if(vis[u])
		continue;
	vis[u]=1;
	int v;
	for(int i=0;i<m;i++)
	{
		v=u;
		int flag=1;
		int sj;
		for(int j=0;j<n;j++)
		{
			sj= (v)&(1<<j);
			if(pt[i].pre[j]=='-'&&sj)
			{
				flag=0;break;
			}
			if(pt[i].pre[j]=='+'&&sj==0)
			{
				flag=0;break;
			}
		}
		if(flag)
		{
			for(int j=0;j<n;j++)
			{
				sj=(v)&(1<<j);
				if(pt[i].num[j]=='-'&&sj)
				{
					v=v^(1<<j);
				}
				if(pt[i].num[j]=='+')
				{
					v=v|(1<<j);
				}
			}
			if(d[v]>d[u]+pt[i].t)
			{
				d[v]=d[u]+pt[i].t;
				q.push(node{v,d[v]});
			}
		}
	}
}
}
void Reverse(char * s)
{
	for(int i=0;i<n/2;i++)
	{
		char temp=s[i];
		s[i]=s[n-1-i];
		s[n-1-i]=temp;
	}
}
int main()
{
	//freopen("in.txt","r",stdin);
	int cas=0;
	while(scanf("%d%d",&n,&m)&&(n+m))
	{
		int t;
		for(int i=0;i<m;i++)
		{
			scanf("%d",&pt[i].t);
			scanf("%s",&pt[i].pre);
			Reverse(pt[i].pre);
			scanf("%s",&pt[i].num);
			Reverse(pt[i].num);
		}
		int cur = (1<<n) - 1;//1代表bug 
		dijstra(cur);
		printf("Product %d\n",++cas);
		if(d[0]!=1<<30)
		printf("Fastest sequence takes %d seconds.\n",d[0]);
		else
		printf("Bugs cannot be fixed.\n");
		printf("\n");
	}
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值