uva658 It's not a Bug, it's a Feature!
Posted tmzengbi
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了uva658 It's not a Bug, it's a Feature!相关的知识,希望对你有一定的参考价值。
传送门https://vjudge.net/problem/UVA-658
看到这题以为是搜索。不过直接搜索估计会G。
正解是隐式图搜索,(看上去挺像bfs的,实际上就是带着权值的bfs,于是就变成了最短路
隐式图搜索就是在一个没有直接给出边的图上进行图论算法(最短路什么的 现在只碰到了最短路
虽然说没有直接给出边,但是可以通过题目给的条件建边,比如这题就是在状态u的时候,枚举所有补丁,看是否可以使用,使用后状态变为v,那么u->v就可以建边
为什么要隐式图搜索呢?正常每个状态枚举补丁也可以呀。问题就是如果预处理所有边,那么空间上无法接受,而且很多状态根本遇不到,所以没必要先把图预处理好。
因为堆优化dijkstra在跑点的时候每个点只会做一次起点,所以边不会重复计算。这样做时间复杂度为O(m2^n)可以接受
还有一个小难点就是check状态u是否能打上补丁,以及如何求打上补丁后的状态。具体实现见代码。
坑点:每次结果后面要两次换行。
#include<iostream> #include<cstdio> #include<cstring> #include<algorithm> #include<queue> #include<vector> using namespace std; typedef long long ll; struct Node { int u,d; Node(int u,int d):u(u),d(d){} bool operator < (const Node N)const { return d>N.d; } }; int n,m,t[110],dis[1100000]; //t指打补丁的时间 char s1[110][21],s2[110][21]; //s1打补丁前 s2打补丁后 bool vis[1100000]; //其他都是写dijkstra的辅助数组 struct Solve { int N,M; void init(int N,int M) //初始化 { this->N=N;this->M=M; memset(vis,false,sizeof vis); } bool check(int x,int now) //状态now能否打上第x个补丁 { int tmp=now; for(int i=0;i<N;i++) { int j=N-i-1; if(s1[x][i]!=‘0‘) { if(s1[x][i]==‘-‘&&((now>>j)&1)) return false; if(s1[x][i]==‘+‘&&((now>>j)&1)==0) return false; } } return true; } void change(int x,int &now) //状态now打上补丁x后变成什么状态 { for(int i=0;i<N;i++) { int j=N-i-1; if(s2[x][i]==‘+‘) now=now|(1<<j); if(s2[x][i]==‘-‘) now=now&(~(1<<j)); } } void showmethedata() //debug用的函数 { for(int i=0;i<(1<<N);i++) printf("%d %d ",i,dis[i]); } int dij() //dijkstra堆优化板子 { priority_queue<Node>q; q.push(Node( (1<<N)-1,0)); for(int i=0;i<(1<<N);i++) dis[i]=1e8; dis[(1<<N)-1]=0; while(!q.empty()) { Node e=q.top();q.pop(); if(e.u==0) return dis[0]; if(vis[e.u]) continue; vis[e.u]=true; for(int i=1;i<=M;i++)//枚举m个补丁找边 { int v=e.u; if(check(i,v)) { change(i,v); if(t[i]+dis[e.u]<dis[v]) { dis[v]=dis[e.u]+t[i]; q.push(Node(v,dis[v])); } } } } return -1; } }solver; int main() { int T=0; // freopen("out.txt","w",stdout); while(scanf("%d%d",&n,&m)==2) { if(n==0&&m==0) break; // if(T) printf(" "); solver.init(n,m); for(int i=1;i<=m;i++) scanf("%d %s %s",&t[i],s1[i],s2[i]); printf("Product %d ",++T); int ans=solver.dij(); if(ans>=0) printf("Fastest sequence takes %d seconds. ",ans); else printf("Bugs cannot be fixed. "); } // system("pause"); }
以上是关于uva658 It's not a Bug, it's a Feature!的主要内容,如果未能解决你的问题,请参考以下文章
UVa 658 - It's not a Bug, it's a Feature!(Dijkstra + 隐式图搜索)
uva 658It's not a Bug, it's a Feature!(图论--Dijkstra算法+二进制表示)
It's not a Bug, It's a Feature! (poj 1482 最短路SPFA+隐式图+位运算)