codeforce_exercise_r3

It’s not a Bug, it’s a Feature!(UVa-658) :

问题描述

题目简述

在这里插入图片描述大意是:现在有一个n个bug都存在的程序,需要给这个程序打补丁修复这所有n个bug,一共有m个补丁可以选择,每个补丁可以使用多次。补丁需要在特定的程序状态下使用,使用后程序的bug状态改变,每个补丁都有运行时长。现在需要求出最短可以修复这n个bug的时长。

输入/输出格式

输入格式:
The input contains several product descriptions. Each description starts with a line containing two
integers n and m, the number of bugs and patches, respectively. These values satisfy 1 ≤ n ≤ 20 and
1 ≤ m ≤ 100. This is followed by m lines describing the m patches in order. Each line contains an
integer, the time in seconds it takes to apply the patch, and two strings of n characters each.
The first of these strings describes the bugs that have to be present or absent before the patch can
be applied. The i-th position of that string is a ‘+’ if bug bi has to be present, a ‘-’ if bug bi has to be
absent, and a ‘0’ if it doesn’t matter whether the bug is present or not.
The second string describes which bugs are fixed and introduced by the patch. The i-th position of
that string is a ‘+’ if bug bi
is introduced by the patch, a ‘-’ if bug bi
is removed by the patch (if it was
present), and a ‘0’ if bug bi
is not affected by the patch (if it was present before, it still is, if it wasn’t,
is still isn’t).
The input is terminated by a description starting with n = m = 0. This test case should not be
processed.
大意是第一行输入n和m代表bug数和补丁数。接下来m行每行3个数,分别代表补丁运行时长,可以加补丁的程序状态,加补丁之后的程序状态(其中“+”代表没有bug,“-”代表有bug,“0”代表有没有bug都无所谓)输入数据有多组,以0 0结束。
输出格式:
For each product description first output the number of the product. Then output whether there is
a sequence of patches that removes all bugs from a product that has all n bugs. Note that in such a
sequence a patch may be used multiple times. If there is such a sequence, output the time taken by the
fastest sequence in the format shown in the sample output. If there is no such sequence, output ‘Bugs
cannot be fixed.’.
Print a blank line after each test case.
大意是:如果可以修复输出修复时间,不能修复输出‘Bugs
cannot be fixed.’。每组之间的输出需要额外输出一个空行。

样例

输入样例:
3 3
1 000 00-
1 00- 0-+
2 0-- -++
4 1
7 0-0+ ----
0 0
输出样例:
Product 1
Fastest sequence takes 8 seconds.
Product 2
Bugs cannot be fixed.

问题分析

解题思路

总体来说题目含义还是比较明显的,求出一个从初始状态到终止状态的最短路长度。状态之间的转移是通过补丁来的。进而可以发现,n个bug的可能状态共有2^n个,但是补丁的数量却很少,最多只有100个。因此,必然有很多状态是一定不会出现的。因此,这个题可以枚举补丁,确定每一步的可能的转移状态。从而大大减少运算。另外由于没有负权边,使用dijkstra算法即可。

参考代码
#include <iostream>
#include <queue>
#include <string>
#include <vector>
#include <cstring>

using namespace std;

const int inf=3e8+5;

class patchnode
{
public:
	string before;
	string after;
	int time;
	patchnode(string &b,string &a,int t)
	{
		before=b;
		after=a;
		time=t;
	}
};

class heapnode
{
public:
	int bug;
	int dist;
	bool operator <(const heapnode& h) const
	{
		return dist>h.dist;
	}
};

vector<patchnode> patchs;
priority_queue<heapnode> pq;
int d[1<<20];
int vis[1<<20];
int m,n;

void init()
{
	while(!pq.empty()) pq.pop();
	patchs.clear();
	memset(d,inf,sizeof(d));
	memset(vis,0,sizeof(vis));
}

int dijkstra()
{
	heapnode start;
	start.bug=(1<<n)-1;
	start.dist=0;
	pq.push(start);
	d[start.bug]=0;
	while(!pq.empty())
	{
		heapnode t=pq.top();
		pq.pop();
		if(t.bug==0) return t.dist;
		if(vis[t.bug]==1) continue;
		vis[t.bug]=1;
		for(int i=0;i<m;i++)
		{
			bool can=true;
			for(int j=0;j<n;j++)
			{
				if(patchs[i].before[j]=='-'&&(t.bug&1<<j)) 
				{
					can=false;
					break;
				}
				if(patchs[i].before[j]=='+'&&!(t.bug&1<<j))
				{
					can=false;
					break;
				}
			}
			if(!can) continue;
			heapnode next;
			next.bug=t.bug;
			next.dist=t.dist+patchs[i].time;
			for(int j=0;j<n;j++)
			{
				if(patchs[i].after[j]=='-') 
				{
					next.bug&=~(1<<j);
				}
				if(patchs[i].after[j]=='+')
				{
					next.bug|=1<<j;
				}
			}
			if(next.dist<d[next.bug])
			{
				d[next.bug]=next.dist;
				pq.push(next);
			}
		} 
	}
	return -1;
}

int main()
{
	int T=0;
	while(1)
	{
		scanf("%d %d",&n,&m);
		if(n==0&&m==0) break;
		init();
		for(int i=1;i<=m;i++)
		{
			string a,b;
			int t;
			cin>>t>>b>>a;
			patchnode p(b,a,t);
			patchs.push_back(p);
		}
		int ans=dijkstra();
		printf("Product %d\n", ++T);
        if(ans<0) printf("Bugs cannot be fixed.\n\n"); 
        else printf("Fastest sequence takes %d seconds.\n\n", ans);
	}
	return 0;
}

心得体会

总体而言是一个dijkstra的比较常规的问题,但是在节点状态上做了一些改变。总体来说思路上还是不难想的。另外就是位运算比较生疏,想了好久。还是练习的太少了。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值