题目链接:点击打开链接
题目描述:补丁在修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)
时间: 2024-10-03 22:25:06