例题11-6 这不是bug,而是特性 UVa658

1.题目描述:点击打开链接

2.解题思路:本题要求找最短的时间,乍一看想用动态规划解决,但可惜这种做法是行不通的,因为状态经过多次转移之后可能会回到原先的状态,即状态图不是DAG。因此联想到用图论上的最短路算法来解决。先把每个状态都看成一个结点,然后用Dijkstra算法解决即可,不过本题与普通的最短路问题略有不同:结点很多,多达2^n个,而且很多状态根本遇不到。所以没必要先把图储存好。(一般的Dijkstra算法用之前都储存好了图)

这里可以直接枚举这m个补丁,看哪一个能用,这样既就能不断地拓展结点了。初始状态是(1<<n)-1,最终的状态是0。本题最终答案是d[0]。本题的一个技巧是先把打补丁之前的状态中必须有的bug用集合来表示,再把无所谓的bug也表示出来,都放到pre数组;用同样的方法预处理打补丁后的状态,放到Next数组中。这样后面的一系列结点就能通过集合之间的运算拓展出来了。

3.代码:

#define _CRT_SECURE_NO_WARNINGS
#include<iostream>
#include<algorithm>
#include<string>
#include<sstream>
#include<set>
#include<vector>
#include<stack>
#include<map>
#include<queue>
#include<deque>
#include<cstdlib>
#include<cstdio>
#include<cstring>
#include<cmath>
#include<ctime>
#include<functional>
using namespace std;

#define N 21
#define M 101
const int INF = 500000000;
int pre[2][M], Next[2][M];//pre数组存放之前的状态,Next数组存放之后的状态
int t[M];
int d[1 << N];
typedef pair<int, int> P;
void dijkstra(int n, int m)//求最短路
{
	for (int i = 0; i < (1 << n); i++)
		d[i] = INF;
	priority_queue<P, vector<P>, greater<P> >q;
	d[(1 << n) - 1] = 0;//全部bug都存在为初始状态
	q.push(P(0, (1 << n) - 1));
	while (!q.empty())
	{
		P u = q.top(); q.pop();
		int x = u.second;
		if (u.first != d[x])continue;
		for (int i = 0; i < m;i++)
		if ((x | pre[0][i]) == x &&(x&pre[1][i]) == x)//枚举所有m个补丁,看是否能打上,有bug时用|,没有用&
		{
			int v = x | Next[0][i];//求并集
			v &= Next[1][i];//求交集
			if (d[v]>d[x] + t[i])
			{
				d[v] = d[x] + t[i];
				q.push(P(d[v], v));
			}
		}
	}
}
int main()
{
	//freopen("t.txt", "r", stdin);
	int n, m;
	int rnd = 0;
	char b1[N], b2[N];
	while (~scanf("%d%d", &n, &m)&& (m || n))
	{
		for (int i = 0; i < m; i++)
		{
			scanf("%d %s %s", t + i, b1, b2);
			pre[0][i] = pre[1][i] = Next[0][i] = Next[1][i] = 0;
			for (int j = 0; j < n; j++)
			{
				if (b1[j] == '+')pre[0][i] |= (1 << j);//pre[0]存放必须有的bug的集合
				if (b1[j] != '-')pre[1][i] |= (1 << j);//pre[1]存放任意状态的bug的集合,同理Next数组
				if (b2[j] == '+')Next[0][i] |= (1 << j);
				if (b2[j] != '-')Next[1][i] |= (1 << j);
			}
		}
		dijkstra(n, m);
		printf("Product %d\n", ++rnd);
		if (d[0] == INF)
			puts("Bugs cannot be fixed.");
		else printf("Fastest sequence takes %d seconds.\n", d[0]);
		puts("");
	}
	return 0;
}
时间: 2024-10-26 22:33:11

例题11-6 这不是bug,而是特性 UVa658的相关文章

hive0.11 hiveserver custom认证bug

最近在测试hive0.11 hiveserver时遇到的一个关于认证的bug,具体表现:在配置中指定了custom的认证方式时,通过beeline连接hiveserver2,发现连接hang住.hive配置: <property> <name>hive.server2.authentication</name>a <value>CUSTOM</value> </property> <property> <name&g

9.11 翻译系列:数据注解特性之--Timestamp【EF 6 Code-First系列】

9.11 翻译系列:数据注解特性之--Timestamp[EF 6 Code-First系列] 原文链接:https://www.entityframeworktutorial.net/code-first/TimeStamp-dataannotations-attribute-in-code-first.aspx EF 6和EF Core都包含TimeStamp数据注解特性.它只能用在实体的byte数组类型的属性上,并且只能用在一个byte数组类型的属性上.然后在数据库中,创建timestam

30条编程名言佳句: 这不是Bug只是未知的特性

以下内容收集自一些优秀的技术书籍章节开头的名言佳句,非常有意思,直接或间接反映了软件开发中的一些事情. 生命太短暂,不要去做一些根本没有人想要的东西.——Ash Maurya 如果你交给某人一个程序,你将折磨他一整天:如果你教某人如何编写程序,你将折磨他一辈子.——David Leinweber 软件设计有两种方式:一种方式是,使软件过于简单,明显没有缺陷:另一种方式是,使软件过于复杂,没有明显的缺陷.——C.A.R. Hoare 其实,我尝试着使 Ruby 更自然,而不是简单.Ruby 看起来

这不是bug,而是语言特性

分析编程语言缺陷的一种方法是把所有的缺陷归于3类:不该做的做了,该做的没做,该做但做得不合适. 在使用switch case时,如果使用缺省的 fall through,请一定在旁边注释,因为97%的情况需要使用break,break跳出的是最近的那层循环或者switch语句. 下面代码,第一次调用和之后调用会出现不同: 1 #include<stdio.h> 2 3 void generate_initializer(const char * string) 4 { 5 static cha

C++11 中的几个新特性

C++11的标准已经确定,除了增加了不少库函数外,在语法方便也得到了许多增强.其中如下几个语法就是我比较喜欢的: 自动类型推导auto 现在c++终于在编译器级别支持类似C#的var关键字了,在c++里的关键字是auto,基本用法如下: auto i = 0;        //int auto c = 'c';    //char auto s = "hello world";    //const char* auto关键字的一个很直观的好处是我们可以简化stl容器遍历里的那个it

C++11中的有趣的新特性(constexpr ) (Range-based for loop)

#include <iostream> #include<stdexcept> using namespace std; //constexpr keyword constexpr int sqare(int tmp) { return tmp*tmp; } int main() { int myArray[sqare(2)]={1,2,3,4}; //Range-based for loop for(int  &tmp : myArray) { tmp++; } for(

OC基础11:基本的C语言特性2

19.定义一个int类型的指针: int count = 10; int *intPtr; intPtr = &count; 然后就可以引用这个指针: x = *intPtr; 带着间接寻址运算符*号才是指针的完整表达形式. 20.&号是取出它标示的变量的地址,*号是把它标示的变量的值当做地址去寻找内容. 注意指针名里面存的是地址.所以用&把某个变量的地址读出来之后,应该是赋给指针的变量名,这时候不能有*号:然后指针的变量名里存有了某个变量的地址,这时候给指针变量名加上*号,加上了

带权并查集(含种类并查集)【经典模板】 例题:①POJ 1182 食物链(经典)②HDU - 1829 A bug&#39;s life(简单) ③hihoCoder 1515 : 分数调查

带权并查集: 增加一个 value 值,并且每次合并和查找的时候需要去维护这个 value 例题一 :POJ 1182 食物链(经典) 题目链接:https://vjudge.net/contest/339425#problem/E 带权并查集的解法 定义两个数组fa[ ]和rela[ ],fa用来判断集合关系,rela用来描述其与根节点的关系.因为关系满足传递性,所以可以推导出给出条件下的当前关系,在判断与之前已有关系是否矛盾. 本题的解法巧妙地利用了模运算,rela数组用0表示同类,1表示当

C++11 标准新特性:Defaulted 和 Deleted 函数

前两天写的铁字中提到了C++的删除函数,今天特地去网上查了查,转载了一篇不错的文章... 转载自 http://www.ibm.com/developerworks/cn/aix/library/1212_lufang_c11new/index.html C++11 标准新特性:Defaulted 和 Deleted 函数 本文将介绍 C++11 标准的两个新特性:defaulted 和 deleted 函数.对于 defaulted 函数,编译器会为其自动生成默认的函数定义体,从而获得更高的代