题目连接(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(最短路径+隐式图+状态压缩)的更多相关文章

  1. UVA 658 状态压缩+隐式图+优先队列dijstla

    不可多得的好题目啊,我看了别人题解才做出来的,这种题目一看就会做的实在是大神啊,而且我看别人博客都看了好久才明白...还是对状态压缩不是很熟练,理解几个位运算用了好久时间.有些题目自己看着别人的题解做 ...

  2. 八数码问题+路径寻找问题+bfs(隐式图的判重操作)

    Δ路径寻找问题可以归结为隐式图的遍历,它的任务是找到一条凑够初始状态到终止问题的最优路径, 而不是像回溯法那样找到一个符合某些要求的解. 八数码问题就是路径查找问题背景下的经典训练题目. 程序框架 p ...

  3. nyoj 21--三个水杯(隐式图bfs)

    三个水杯 时间限制:1000 ms  |  内存限制:65535 KB 难度:4 描述 给出三个水杯,大小不一,并且只有最大的水杯的水是装满的,其余两个为空杯子.三个水杯之间相互倒水,并且水杯没有标识 ...

  4. 【UVA】658 - It&#39;s not a Bug, it&#39;s a Feature!(隐式图 + 位运算)

    这题直接隐式图 + 位运算暴力搜出来的,2.5s险过,不是正法,做完这题做的最大收获就是学会了一些位运算的处理方式. 1.将s中二进制第k位变成0的处理方式: s = s & (~(1 < ...

  5. UVA - 658 It's not a Bug, it's a Feature! (隐式图的最短路,位运算)

    隐式的图搜索,存不下边,所以只有枚举转移就行了,因为bug的存在状态可以用二进制表示,转移的时候判断合法可以用位运算优化, 二进制pre[i][0]表示可以出现的bug,那么u&pre[i][ ...

  6. Ural 1741 Communication Fiend(隐式图+虚拟节点最短路)

    1741. Communication Fiend Time limit: 1.0 second Memory limit: 64 MB Kolya has returned from a summe ...

  7. HDU 2825 Wireless Password ( Trie图 && 状态压缩DP )

    题意 : 输入n.m.k意思就是给你 m 个模式串,问你构建长度为 n 至少包含 k 个模式串的方案有多少种 分析 : ( 以下题解大多都是在和 POJ 2778 && POJ 162 ...

  8. hdoj 1495 非常可乐【bfs隐式图】

    非常可乐 Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)Total Submis ...

  9. 倒水问题 (FillUVa 10603) 隐式图

    题意:本题的题意是给你三个杯子,第一二个杯子是空的,第三个杯子装满水,要求是量出一定容量d升的水.若是得不到d升的水,那就让某一个杯子里面的水达到d',使得d'尽量接近d升. 解题思路:本题是给出初始 ...

随机推荐

  1. [POJ 1204]Word Puzzles(Trie树暴搜&amp;AC自己主动机)

    Description Word puzzles are usually simple and very entertaining for all ages. They are so entertai ...

  2. BZOJ3243 [Noi2013]向量内积 【乱搞】

    题目链接 BZOJ3243 题解 模数只有\(2\)或\(3\),可以大力讨论 如果模数为\(2\),乘积结果只有\(1\)或\(0\) 如果一个向量和前面所有向量乘积都为\(1\),那么其和前面向量 ...

  3. 前缀统计 [Trie]

    前缀统计 描述 给定N个字符串S1,S2...SN,接下来进行M次询问,每次询问给定一个字符串T,求S1-SN中有多少个字符串是T的前缀.输入字符串的总长度不超过10^6,仅包含小写字母. 输入格式 ...

  4. UVA10480:Sabotage(最小割+输出)

    Sabotage 题目链接:https://vjudge.net/problem/UVA-10480 Description: The regime of a small but wealthy di ...

  5. 两个神奇的函数~~~sscanf、atoi

    sscanf 对你没有看错 多了一个s 这个函数有什么作用呢 功能:读取字符串中的int.double.long.long long .float and so on 类型的数据 譬如说 我现在读入了 ...

  6. tcp/ip网络协议学习

    链路层介绍 网络层协议的数据单元是 IP 数据报 ,而数据链路层的工作就是把网络层交下来的 IP 数据报 封装为 帧(frame)发送到链路上,以及把接收到的帧中的数据取出并上交给网络层. 以太网 以 ...

  7. SpringMVC学习 -- ModelAndView , Model , ModelMap , Map 及 @SessionAttributes 的使用

    输出模型数据: ModelAndView:处理方法返回值类型为 ModelAndView 时 , 其中包含视图和模型信息.方法体即可通过该对象添加模型数据 , 即 SpringMVC 会把 Model ...

  8. NYOJ 38 布线问题 (最小生成树 prim)

    题目链接 描述 南阳理工学院要进行用电线路改造,现在校长要求设计师设计出一种布线方式,该布线方式需要满足以下条件: 1.把所有的楼都供上电. 2.所用电线花费最少 输入 第一行是一个整数n表示有n组测 ...

  9. rtmp服务端实现

    前言 网上好像没一篇讲的很完善的,可能和公司保密有关吧.先就最让人困惑(至少我是这样)且网上也很少找到答案的一个点讲一下id各是什么意思? (如果我哪里理解错了,希望大神指出,毕竟我也是看了好多资料及 ...

  10. Kuangbin带你飞 AC自动机

    模板: struct Ac_Automation { int ch[MAXNNODE][SIGMA_SIZE]; int val[MAXNNODE]; int fail[MAXNNODE],last[ ...