uva658(最短路径+隐式图+状态压缩)
题目连接(vj):https://vjudge.net/problem/UVA-658
题意:补丁在修正 bug 时,有时也会引入新的 bug。假定有 n(n≤20)个潜在 bug 和 m(m≤100) 个补丁,每个补丁用两个长度为 n 的字符串表示,其中字符串的每个位置表示一个 bug。第一 个串表示打补丁之前的状态(“-” 表示该 bug 必须不存在,“+” 表示必须存在,0 表示无所 谓),第二个串表示打补丁之后的状态(“-” 表示不存在,“+” 表示存在,0 表示不变)。每 个补丁都有一个执行时间,你的任务是用最少的时间把一个所有 bug 都存在的软件通过打补 丁的方式变得没有 bug。一个补丁可以打多次。 在任意时刻,每个 bug 可能存在也可能不存在,所以可以用一个 n 位二进制串表示当前软 件的 “状态”。打完补丁之后,bug 状态会发生改变,对应 “状态转移”。是不是很像动态规 划?可惜动态规划是行不通的,因为状态经过多次转移之后可能会回到以前的状态,即状态 图并不是 DAG。如果直接用记忆化搜索,会出现无限递归。 正确的方法是把状态看成结点,状态转移看成边,转化成图论中的最短路径问题,然后 使用 Dijkstra 或 Bellman-Ford 算法求解。不过这道题和普通的最短路径问题不一样:结点很 多,多达 2 n 个,而且很多状态根本遇不到(即不管怎么打补丁,也不可能打成那个状态), 所以没有必要像前面那样先把图储存好。 还记得第 7 章中介绍的 “隐式图搜索” 吗?这里也可以用相同的方法:当需要得到某个结 点 u 出发的所有边时,不是去读 G[u],而是直接枚举所有 m 个补丁,看看是否能打得上。不管 是 Dijsktra 算法还是 Bellman-Ford 算法,这个方法都适用。本题很经典,强烈建议读者编程实现。
以上题意以及思路来自紫书
解题思路:抽象成最短路问题,因为状态(节点)太多,而且很多不会出现,所以不能单独建完图再跑最短路,所以采用隐式图,每次扩展遍历一遍已知补丁,匹配成功则看是否可以松弛,记录松弛后的状态。
当前状态唯一确定,所以压缩为一个n位二进制串,0表示无bug,1表示有,而补丁的状态不唯一确定,所以用两个二进制串表示,has串和no串,has串1表示该位置一定有,no串1表示该位置一定无。
匹配方法:cur表示当前状态。如果 cur&no==0并且cur|yes=cur 则匹配成功,匹配成功后松弛后的状态为 v=(u|p.to_has)&(~p.to_no)。然后跑dijkstra即可。
代码如下:
#include<bits/stdc++.h>
#define MAX (1<<20)+10
#define INF 0x3fffffff
using namespace std;
struct data
{
int from_no,from_has,to_no,to_has,dist;
} patch[];
struct heapnode
{
int d,u;
bool operator < (const heapnode& rhs) const
{
return d>rhs.d;
}
};
int l,m;
bool vis[MAX];
long long d[MAX];
void init(void)
{
; i<m; i++)
{
patch[i].from_has=;
patch[i].from_no=;
patch[i].to_has=;
patch[i].to_no=;
}
memset(vis,,sizeof(vis));
; i<MAX; i++)
d[i]=INF;
}
bool dijkstra(void)
{
priority_queue<heapnode> Q;
<<l)-;
d[s]=;;
Q.push((heapnode){,s});
while(!Q.empty())
{
heapnode x=Q.top();
Q.pop();
int u=x.u;
if(vis[u]) continue;
vis[u]=;
; i<m; i++)
{
data &p=patch[i];
if(!(u&p.from_no)&&((u|p.from_has)==u))//匹配成功
{
int v=(u|p.to_has)&(~p.to_no);
if(d[v]>d[u]+p.dist)
{
d[v]=d[u]+p.dist;
Q.push((heapnode){d[v],v});
}
}
}
}
]==INF)
;
;
}
int main()
{
;
while(~scanf("%d%d",&l,&m)&&l)
{
init();
; i<m; i++)
{
],to[];
int dis;
scanf("%d%s%s",&dis,from,to);
patch[i].dist=dis;
; j<l; j++)
{
<<j);
<<j);
<<j);
<<j);
}
}
printf("Product %d\n",++T);
if(dijkstra())
printf(]);
else
printf("Bugs cannot be fixed.\n");
printf("\n");
}
}
uva658(最短路径+隐式图+状态压缩)的更多相关文章
- UVA 658 状态压缩+隐式图+优先队列dijstla
不可多得的好题目啊,我看了别人题解才做出来的,这种题目一看就会做的实在是大神啊,而且我看别人博客都看了好久才明白...还是对状态压缩不是很熟练,理解几个位运算用了好久时间.有些题目自己看着别人的题解做 ...
- 八数码问题+路径寻找问题+bfs(隐式图的判重操作)
Δ路径寻找问题可以归结为隐式图的遍历,它的任务是找到一条凑够初始状态到终止问题的最优路径, 而不是像回溯法那样找到一个符合某些要求的解. 八数码问题就是路径查找问题背景下的经典训练题目. 程序框架 p ...
- nyoj 21--三个水杯(隐式图bfs)
三个水杯 时间限制:1000 ms | 内存限制:65535 KB 难度:4 描述 给出三个水杯,大小不一,并且只有最大的水杯的水是装满的,其余两个为空杯子.三个水杯之间相互倒水,并且水杯没有标识 ...
- 【UVA】658 - It's not a Bug, it's a Feature!(隐式图 + 位运算)
这题直接隐式图 + 位运算暴力搜出来的,2.5s险过,不是正法,做完这题做的最大收获就是学会了一些位运算的处理方式. 1.将s中二进制第k位变成0的处理方式: s = s & (~(1 < ...
- UVA - 658 It's not a Bug, it's a Feature! (隐式图的最短路,位运算)
隐式的图搜索,存不下边,所以只有枚举转移就行了,因为bug的存在状态可以用二进制表示,转移的时候判断合法可以用位运算优化, 二进制pre[i][0]表示可以出现的bug,那么u&pre[i][ ...
- Ural 1741 Communication Fiend(隐式图+虚拟节点最短路)
1741. Communication Fiend Time limit: 1.0 second Memory limit: 64 MB Kolya has returned from a summe ...
- HDU 2825 Wireless Password ( Trie图 && 状态压缩DP )
题意 : 输入n.m.k意思就是给你 m 个模式串,问你构建长度为 n 至少包含 k 个模式串的方案有多少种 分析 : ( 以下题解大多都是在和 POJ 2778 && POJ 162 ...
- hdoj 1495 非常可乐【bfs隐式图】
非常可乐 Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others)Total Submis ...
- 倒水问题 (FillUVa 10603) 隐式图
题意:本题的题意是给你三个杯子,第一二个杯子是空的,第三个杯子装满水,要求是量出一定容量d升的水.若是得不到d升的水,那就让某一个杯子里面的水达到d',使得d'尽量接近d升. 解题思路:本题是给出初始 ...
随机推荐
- 周记【距gdoi:91天】
这星期挺没状态的.听蔡大神讲组合游戏,然后欢乐得以为自己懂了,然后看到题目就懵了,然后就各种乱各种走神……但是某大神们(kpm和child)疯狂地切题.然后又颓废了两个晚上后决定滚回去文化课(oi没状 ...
- [Leetcode] String to integer atoi 字符串转换成整数
Implement atoi to convert a string to an integer. Hint: Carefully consider all possible input cases. ...
- OI中组合数的若干求法与CRT
OI中组合数的若干求法与CRT 只是下决心整理一下子呢~ 说明:本篇文章采用\(\binom{a}{b}\)而不是\(C_{a}^b\),以\(p\)指代模数,\(fac_i\)指代\(i!\),\( ...
- Mysql History list length 值太大引起的问题
1. 环境 Mysql 主从 Mysql版本:5.1.49-log 系统:Red Hat Enterprise Linux Server release 5.4 64bit 2. 表面现象 数据库操 ...
- TSP问题之状压dp法
首先,我们先来认识一下什么叫做TSP问题 旅行商问题,即TSP问题(Traveling Salesman Problem)又译为旅行推销员问题.货郎担问题,是数学领域中著名问题之一.假设有一个旅行商人 ...
- socket编程 ------ 建立 TCP 服务器和客户端流程(阻塞方式)
服务器端: 服务器端先创建一个socket,然后把这个socket绑定到端口上,接着让它向tcp/ip协议栈请求一个监听服务并创建一个accept队列来接受客户端请求. void creat_tcpS ...
- maven项目在eclipse tomcat正常运行
转摘自:http://binary.duapp.com/2013/10/1577.html 配置下部署路径即可.
- HTML5学习之新增标签
转自:http://www.cnblogs.com/fly_dragon/archive/2012/05/25/2516142.html 作者:FlyDragon 一.引言 在本节中,笔者将向大家讲述 ...
- 原型prototype与原型链__proto__
在 javascript 中我们会约定俗成,如果一个方法是被 new 出来使用的,那么该方法名首字母通常会大写,例如下面代码块中的 Person. var Person = function(name ...
- Fragment里使用 PhoneGap 的 CordovaWebView
首先说明一下为什么要使用 CordovaWebView 而不直接使用 WebView 呢?由于 Android4.4 版本之后对 WebView 做了很大的改变,具体参考 这篇文章:理解WebKit和 ...