poj1482(隐式图求最短路)

题目链接

题意:补丁在修正bug时,有时也会引入新的bug。假定有n个潜在的bug m个补丁,每个补丁用两个长度为n的字符串表示,其中字符串的每个位置表示一个bug,第一个串表示打补丁之前的状态(‘-‘表示该bug必须不存在,’+‘表示必须存在,0表示无所谓,第二个串表示打补丁之后的状态(-‘表示不存在,’+‘表示存在,0表示不变)。每个补丁都有一个执行时间,你的任务使用最少的时间把一个bug都存在的软件通过打补丁的方式变得没有bug。一个补丁可以打多次。

解法:状压表示每个补丁的存在与否。隐式搜索,会有很多状态根本搜不到,spfa直接搜索即可。对于每次都枚举使用所有的补丁修补并松弛得到的状态。

代码:

/******************************************************
* @author:xiefubao
*******************************************************/
#pragma comment(linker, "/STACK:102400000,102400000")
#include <iostream>
#include <cstring>
#include <cstdlib>
#include <cstdio>
#include <queue>
#include <vector>
#include <algorithm>
#include <cmath>
#include <map>
#include <set>
#include <stack>
#include <string.h>
//freopen ("in.txt" , "r" , stdin);
using namespace std;

#define eps 1e-8
#define zero(_) (abs(_)<=eps)
const double pi=acos(-1.0);
typedef long long LL;
const int Max=10100000;
const LL INF=0x3FFFFFFF;
int state[(1<<20)+10];
int n,m;
struct bug
{
    int cost;
    char start[22];
    char end[22];
} bugs[1200];
bool operator<(const bug& a,const bug& b)
{
    return a.cost<b.cost;
}
int que[Max];
bool rem[(1<<20)+10];
int getstate(int st,int j)
{
    for(int i=0; i<n; i++)
    {
        if(bugs[j].start[i]=='-'&&(st&(1<<i)))
            return -1;
        if(bugs[j].start[i]=='+'&&!(st&(1<<i)))
            return -1;
    }
    int re=0;
    for(int i=0; i<n; i++)
    {
        if(bugs[j].end[i]=='+')
            re|=(1<<i);
        if(bugs[j].end[i]=='0')
            re|=st&(1<<i);
    }
    return re;
}
int main()
{
    int kk=1;
    while(cin>>n>>m)
    {
        if(n==0&&m==0)
            break;
        for(int i=0; i<m; i++)
            scanf("%d%s%s",&bugs[i].cost,bugs[i].start,bugs[i].end);
        sort(bugs,bugs+m);
        memset(state,-1,sizeof state);
        memset(rem,0,sizeof rem);
        state[(1<<n)-1]=0;
        rem[(1<<n)-1]=1;
        int left=0,right=1;
        que[0]=(1<<n)-1;
        while(left<right)
        {
            //cout<<left<<endl;
            int t=que[left++];
            for(int i=0; i<m; i++)
            {
                int st=getstate(t,i);
                if(st!=-1&&(state[st]==-1||state[st]>state[t]+bugs[i].cost))
                {
                    state[st]=state[t]+bugs[i].cost;
                    if(!rem[st])
                        que[right++]=st,rem[st]=1;
                }
            }
            rem[t]=0;
        }
        printf("Product %d\n",kk++);
        if(state[0]==-1)
            puts("Bugs cannot be fixed.");
        else
        {
            printf("Fastest sequence takes %d seconds.\n",state[0]);
        }
        cout<<endl;
    }
    return 0;
}
时间: 2024-08-27 05:51:58

poj1482(隐式图求最短路)的相关文章

It&amp;#39;s not a Bug, It&amp;#39;s a Feature! (poj 1482 最短路SPFA+隐式图+位运算)

Language: Default It's not a Bug, It's a Feature! Time Limit: 5000MS   Memory Limit: 30000K Total Submissions: 1353   Accepted: 516 Description It is a curious fact that consumers buying a new software product generally do not expect the software to

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

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

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

Δ路径寻找问题可以归结为隐式图的遍历,它的任务是找到一条凑够初始状态到终止问题的最优路径, 而不是像回溯法那样找到一个符合某些要求的解. 八数码问题就是路径查找问题背景下的经典训练题目. 程序框架 process()  初始化vis数组,初始化初始节点到目标节点的移动距离 dfs()搜索到每一个节点,如果不是目标节点,对其依次扩展所有子节点,并判重,全部子节点搜索完全后,改变父节点:如果是目标节点成功返回 输出最少移动步数 input: 2 6 4 1 3 7 0 5 8 8 1 5 7 3 6

隐式图的遍历

好久不看都快忘了... 一些奇怪的问题可以归为隐式图的遍历 NEUOJ544 Problem Description there is an old saying,"You can not do anything without water"or"Water is the source of life". Besides, human beings are made of water. Sister Wang thinks that woman is made of

hdu1818 It&#39;s not a Bug, It&#39;s a Feature!(隐式图最短路径Dijkstra)

题目链接:点击打开链接 题目描述:补丁在修bug时,有时也会引入新的bug,假设有n(n<=20)个潜在的bug和m(m<=100)个补丁,每个补丁用两个长度为n的字符串表示,其中字符串的每个位置表示一个bug.第一个串表示打补丁之前的状态('-'表示在该位置不存在bug,'+'表示该位置必须存在bug,0表示无所谓),第二个串表示打补丁之后的状态('-'表示不存在,'+'表示存在,0表示不变).每个补丁都有一个执行时间,你的任务是用最少的时间把一个所有bug都存在的软件通过打补丁的方式变得没

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

这题直接隐式图 + 位运算暴力搜出来的,2.5s险过,不是正法,做完这题做的最大收获就是学会了一些位运算的处理方式. 1.将s中二进制第k位变成0的处理方式: s = s & (~(1 << pos)); 将s中二进制第k位变成1的处理方式: s = s | (1 << pos); 2.二进制运算: [1] & : 1 & 1 = 1 , 1 & 0 = 0 , 0 & 0 = 0; 快速判断奇偶性: if(a & 1);//为奇数

倒水问题 (FillUVa 10603) 隐式图

题意:本题的题意是给你三个杯子,第一二个杯子是空的,第三个杯子装满水,要求是量出一定容量d升的水.若是得不到d升的水,那就让某一个杯子里面的水达到d',使得d'尽量接近d升. 解题思路:本题是给出初始状态,让你寻找一条通往目标的路径,此题也可看成是有向图中在起点和目标点之间寻找一条最短路径,但是这个最短路径不是距离最短而是倒的水最少,所以这题类似于Dijkstra算法求最短路,利用广搜,一直选当前水量最少的结点进行扩展,所以可以建立一个优先队列来存储下一次要访问的结点,同时将访问过的结点标记一下

hdoj 1226 超级密码 【隐式图BFS】

题目:hdoj 1226 超级密码 分析:这题属于隐式图搜索,状态不是很明显,需要自己建立. 其实搜索说白了就是暴力. 这个题目就是,首先对给出的可以组成的所有的数依次枚举,长度从小到大. 比如第一组样例,因为0不能出现在首位,那么我们枚举首位为1 和 7 看看漫步满足, 满足的话枚举第二位10 11 17 以及 70 71 77 顺便保存他们取余 n 之后的值,这样就可以剪枝,搜索过的就不用重复搜索了. 要求最早出现的BFS即可,第一个搜到的就是. 注意长度不大于500 AC代码: #incl

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

1741. Communication Fiend Time limit: 1.0 second Memory limit: 64 MB Kolya has returned from a summer camp and now he's a real communication fiend. He spends all his free time on the Web chatting with his friends via ICQ. However, lately the protocol