标签:
题目链接:点击打开链接
题目描述:补丁在修bug时,有时也会引入新的bug,假设有n(n<=20)个潜在的bug和m(m<=100)个补丁,每个补丁用两个长度为n的字符串表示,其中字符串的每个位置表示一个bug。第一个串表示打补丁之前的状态(‘-‘表示在该位置不存在bug,‘+‘表示该位置必须存在bug,0表示无所谓),第二个串表示打补丁之后的状态(‘-’表示不存在,‘+‘表示存在,0表示不变)。每个补丁都有一个执行时间,你的任务是用最少的时间把一个所有bug都存在的软件通过打补丁的方式变得没bug。一个补丁可以打多次。
解题思路:
首先思考动态规划是否可行?显然某个状态经过多次补丁修过之后可能会回到某一状态,并不是DAG,如果使用记忆化搜索会出现无限递归
正确的做法:把每个状态看成结点,状态转移看成边,转化成图论中的最短路径问题,然后使用Dijkstra算法求解。不过这道题和普通的最短路径问题不一样:节点很多,多达2^n个,而且很多状态根本遇不到,所以没有必要像前面那样把图存好。这里我们可以像隐式图搜索一样,对某个结点在搜索的过程中进行扩展(枚举所有的补丁)
代码:
#include <bitset>
#include <cstdio>
#include <iostream>
#include <queue>
#define MAXN 1100000
#define INF 1e9+7
using namespace std;
typedef bitset<20> bit;
struct patches{
int nt;
string from;
string to;
patches(int _nt,string _from,string _to):nt(_nt),from(_from),to(_to){}
}*pts[101];
struct node{
int ct;
bit bits;
node(int _ct,bit _bits):ct(_ct),bits(_bits){}
bool operator<(const node& b)const{
return ct>b.ct;
}
};
int n,m;
bit from;
int dis[MAXN];
bool check(bit bt1,string bt2){
for(int i=0;i<n;++i){
if(bt2[i]=='+'&&!(bt1.test(i)))
return false;
if(bt2[i]=='-'&&bt1.test(i))
return false;
}
return true;
}
void change(bit& bt1,string bt2){
for(int i=0;i<n;++i){
if(bt2[i]=='+')
bt1.set(i);
else if(bt2[i]=='-')
bt1.reset(i);
}
}
void dijkstar(){
priority_queue<node> Q;
while(!Q.empty()) Q.pop();
int tsize=from.to_ulong();
for(int i=0;i<=tsize;i++)
dis[i]=INF;
dis[from.to_ulong()]=0;
Q.push(node(0,from));
while(!Q.empty()){
node tmp=Q.top();Q.pop();
bit tbit(tmp.bits);
if(tbit.to_ulong()==0)
return;
if(tmp.ct>dis[tbit.to_ulong()])
continue;
for(int i=0;i<m;i++){
if(check(tbit,pts[i]->from)){
bit tt(tbit);
change(tt,pts[i]->to);
int tt1=tbit.to_ulong();
int tt2=tt.to_ulong();
if(tt1<INF&&dis[tt2]>(dis[tt1]+pts[i]->nt)){
dis[tt2]=dis[tt1]+pts[i]->nt;
Q.push(node(dis[tt2],tt));
}
}
}
}
}
int main(){
int cas=1;
while((cin>>n>>m)&&(n!=0||m!=0)){
string a,b;
int tt;
for(int i=0;i<m;++i){
cin>>tt>>a>>b;
pts[i]=new patches(tt,a,b);
}
from.reset();
for(int i=0;i<n;i++)
from.set(i);
dijkstar();
printf("Product %d\n",cas);
if(dis[0]<INF)
printf("Fastest sequence takes %d seconds.\n",dis[0]);
else
printf("Bugs cannot be fixed.\n");
cas++;
printf("\n");
}
return 0;
}
收获:
1、隐式图上的Djkstra
2、bitset的使用
版权声明:本文为博主原创文章,未经博主允许不得转载。
hdu1818 It's not a Bug, It's a Feature!(隐式图最短路径Dijkstra)
标签:
原文地址:http://blog.csdn.net/mengxingyuanlove/article/details/47450825