状态转移的最短路 隐式图搜索 UVA 658

紫书365

题目大意:给你n个全都是bug的东西,然后每次可以修复,给你修复前后的状态,问最后如果能把bug全都修复,最少需要多少时间。

思路:从最初状态开始,然后枚举bug即可。

表示priority里面的bool operator和单纯的sort的定义的大小于号是不一样的啊,如果你想用sort来计算struct从小到大的的话是这样的

struct Node{
    int bugs, dist;
    bool operator < (const Node &a) const{
        return dist < a.dist;
    }
    Node(int b = 0, int d = 0): bugs(b), dist(d){}
};

而优先队列是这样的

struct Node{
    int bugs, dist;
    bool operator < (const Node &a) const{
        return dist > a.dist;
    }
    Node(int b = 0, int d = 0): bugs(b), dist(d){}
};

区分一下大小于号就好了

//看看会不会爆int!数组会不会少了一维!
//取物问题一定要小心先手胜利的条件
#include <bits/stdc++.h>
using namespace std;
#define LL long long
#define ALL(a) a.begin(), a.end()
#define pb push_back
#define mk make_pair
#define fi first
#define se second
const int inf = 0x3f3f3f3f;
const int maxn = (1 << 20) + 5;
const int maxm = 100 + 5;
int n, m;
int t[maxm], d[maxn];
bool vis[maxn];
char b[maxm][30], e[maxm][30];
struct Node{
    int bugs, dist;
    bool operator < (const Node &a) const{
        return dist > a.dist;
    }
    Node(int b = 0, int d = 0): bugs(b), dist(d){}
};

int solve(){
    memset(vis, false, sizeof(vis));
    memset(d, 0x3f, sizeof(d));
    priority_queue<Node> que;
    int tmp = (1 << n) - 1;
    que.push(Node(tmp, 0));
    d[tmp] = 0; vis[tmp] = 1;
    while (!que.empty()){
        Node u = que.top(); que.pop();
        if (u.bugs == 0) return u.dist;
        for (int i = 0; i < m; i++){
            int from = u.bugs;
            bool flag = false;
            for (int j = 0; j < n; j++){
                if (b[i][j] == ‘-‘ && (from & (1 << j))) {flag = true; break;}
                if (b[i][j] == ‘+‘ && !(from & (1 << j))) {flag = true; break;}
            }
            if (flag) continue;
            int to = from;
            for (int j = 0; j < n; j++){
                if (e[i][j] == ‘-‘ && (from & (1 << j))) to ^= 1 << j;
                if (e[i][j] == ‘+‘) to |= 1 << j;
            }
            if (d[to] > d[from] + t[i] && !vis[to]){
                d[to] = d[from] + t[i];
                vis[to] = false;
                que.push(Node(to, d[to]));
            }
        }
    }
    return -1;
}

int main(){
    int kase = 0;
    while (scanf("%d%d", &n, &m) && n){
        for (int i = 0; i < m; i++){
            scanf("%d", t + i);
            scanf("%s%s", b[i], e[i]);
        }
        printf("Product %d\n", ++kase);
        int ans = solve();
        if (ans < 0) printf("Bugs cannot be fixed.\n");
        else printf("Fastest sequence takes %d seconds.\n", ans);
        printf("\n");
    }
    return 0;
}

时间: 2024-09-29 09:06:42

状态转移的最短路 隐式图搜索 UVA 658的相关文章

UVa658 It&#39;s not a Bug, it&#39;s a Feature! (最短路,隐式图搜索)

链接:http://vjudge.net/problem/UVA-658 分析:Dijkstra求隐式图最短路. 1 #include <cstdio> 2 #include <queue> 3 using namespace std; 4 5 const int maxn = 20; 6 const int maxm = 100 + 5; 7 const int INF = 1000000000; 8 9 int n, m, t[maxm], vis[1 << max

UVa 658 - It&#39;s not a Bug, it&#39;s a Feature!(Dijkstra + 隐式图搜索)

链接: https://uva.onlinejudge.org/index.php?option=com_onlinejudge&Itemid=8&page=show_problem&problem=599 题意: 补丁在修正bug时,有时也会引入新的bug.假定有n(n≤20)个潜在bug和m(m≤100)个补丁,每个补丁用两个长度为n的字符串表示,其中字符串的每个位置表示一个bug.第一个串表示打补丁之前的状态("-"表示该bug必须不存在,"+&

UVa10603 Fill (隐式图搜索+Dijkstra)

链接:http://acm.hust.edu.cn/vjudge/problem/19527分析:隐式图搜索,从初始状态(0,0,c)开始,维护一个到达k升水所需的最少倒水量ans.结点状态设计为v[3]表示当前状态三个杯子中的水量和到达此状态的倒水量.用一个二维vis判重,因为只要第1,2个杯子里的水量确定第3个杯子里的水量也就确定了,所以二维就足以表示了.然后跑一边Dijkstra,用优先队列每次取出倒水量最少的的结点进行扩展,然后用到了一个定序的技巧,规定从i号杯子倒到j号杯子里,生成一个

HDU5012Dice(隐式图搜索)

题目:HDU5012Dice(隐式图搜索) 题目大意:给你一个两个色子,规定每个面的序号,现在给你这两个色子的每个面的颜色(a1,a2,a3,a4,a5,a5)(b1,b2,b3,b4,b5,b6).现在要求比通过下面的四种旋转使得a序列和b序列一样.可以的话输出最少的旋转步数,不能输出-1. 解题思路:bfs + map判重.就是四种旋转的状态要弄清楚. 代码: #include <cstdio> #include <cstring> #include <map> u

zoj 3814 Sawtooth Puzzle(隐式图搜索)

题目链接:zoj 3814 Sawtooth Puzzle 题目大意:给定一个9宫拼图,每次可以挑选一个位置顺时针旋转,和普通拼图不一样的是每块拼图周围可能有齿转动一个可能导致全部拼图转变. 解题思路:隐式图搜索,9块拼图最多49个状态,对于每个状态枚举转动的位置,考虑转动的状态.一开始转移是用bfs写的,但是由于频繁申请队列,然后时间爆了 #include <cstdio> #include <cstring> #include <queue> #include &l

UVA - 10603 Fill(隐式图搜索)

题目大意:经典的倒水问题.给你三个瓶子,体积为a,b,c. 刚开始a,b是空的,c是满的,现在要求你到出体积为d的水.倒水的规则为,要么倒水方为空,要么接水方满 问倒到容量为d时,倒水的最小体积是多少,如果不能倒出体积为d的水,找出d' < d,最接近d的d'和最小的体积 解题思路:刚才时以为直接bfs,用vis标记一下就结束了,结果WA了.为什么会WA,因为我这样求的是倒水次数最少的,而不是倒水体积最小的,WA是肯定的了 接着将vis数组改成int型的,纪录达到这个状态时倒水的体积,结果可想而

uva-321-暴力枚举-隐式图搜索

题意:给你n个房间,有许多灯的控制开关,i房间灯的开关在j房间,未开灯的房间不能进,i房间和j房间之间如果没有门,也不能从i进入到j,开始房间是1,并且灯是开着的,问你是否能够走到最后一个房间n,并且此时其他房间的灯都是关着的.如果存在多个解,输出操作步数最小的操作序列. 范围:n<=10, 解题思路:设状态为,当前的房间编号+当前其他房间灯的状态.所以总的状态为N*2^N,最大值10*1024,裸枚举. 注意,这道题目每次枚举都必须从房间编码1-N,要不然会wa,而且,PE也wa.使用了位标志

倒水问题 隐式图搜索问题

#include <cstdio> #include <iostream> #include <algorithm> #include <queue> #include <stack> #include <climits> #include <cstring> #include <cmath> #include <map> #include <set> using namespace s

uva658(最短路径+隐式图+状态压缩)

题目连接(vj):https://vjudge.net/problem/UVA-658 题意:补丁在修正 bug 时,有时也会引入新的 bug.假定有 n(n≤20)个潜在 bug 和 m(m≤100) 个补丁,每个补丁用两个长度为 n 的字符串表示,其中字符串的每个位置表示一个 bug.第一 个串表示打补丁之前的状态("-" 表示该 bug 必须不存在,"+" 表示必须存在,0 表示无所 谓),第二个串表示打补丁之后的状态("-" 表示不存在,