uva658 (shortest path + implicit graph + state compression)

Problem link (vj): https://vjudge.net/problem/UVA-658

Question: Patches sometimes introduce new bugs when they fix bugs. Suppose there are n (n≤20) potential bugs and m (m≤100) patches, each patch is represented by two strings of length n, where each position of the string represents a bug. The first string represents the state before patching ("-" means the bug must not exist, "+" means it must exist, 0 means it doesn't matter), and the second string represents the state after patching ("-" means it does not exist , "+" means existence, 0 means unchanged). Each patch has an execution time, and your task is to patch a software with all bugs to become bug-free in the least amount of time. A patch can be played multiple times. At any time, each bug may or may not exist, so an n-bit binary string can represent the current "state" of the software. After patching, the bug state will change, corresponding to "state transition". Is it a lot like dynamic programming? Unfortunately, dynamic programming does not work, because the state may return to the previous state after many transitions, that is, the state diagram is not a DAG. If you use memoization search directly, there will be infinite recursion. The correct method is to regard the state as a node and the state transition as an edge, transform it into the shortest path problem in graph theory, and then use Dijkstra or Bellman-Ford algorithm to solve it. However, this problem is different from the ordinary shortest path problem: there are many nodes, as many as 2 n, and many states are not encountered at all (that is, no matter how patched, it is impossible to be in that state), so there is no need to like Save the image as before. Remember "Implicit Graph Search" from Chapter 7? The same method can be used here: when you need to get all the edges from a node u, instead of reading G[u], you can directly enumerate all m patches to see if you can hit them. This method works regardless of Dijsktra's algorithm or Bellman-Ford's algorithm. This topic is very classic, and it is strongly recommended that readers implement it by programming. 

The above questions and ideas come from Zishu

Problem- solving idea: abstract into the shortest path problem, because there are too many states (nodes), and many will not appear, so it is not possible to build the graph alone and then run the shortest path. If the match is successful, see if it can be relaxed, and record the relaxed state.

The current state is uniquely determined, so it is compressed into an n-bit binary string, 0 means no bug, 1 means yes, and the state of the patch is not uniquely determined, so it is represented by two binary strings, the has string and the no string, and the has string 1 indicates the The position must be present, and the no string 1 means that the position must be absent.

Matching method: cur indicates the current state. If cur&no==0 and cur|yes=cur, the match is successful, and the relaxed state is v=(u|p.to_has)&(~p.to_no). Then run dijkstra.

code show as below:

#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[105];

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)
{
    for(int i=0; i<m; i++)
    {
        patch[i].from_has=0;
        patch[i].from_no=0;
        patch[i].to_has=0;
        patch[i].to_no=0;
    }
    memset(vis,0,sizeof(vis));
    for(int i=0; i<MAX; i++)
        d[i]=INF;
}

bool dijkstra(void)
{
    priority_queue<heapnode> Q;
    int s=(1<<l)-1;
    d[s]=0;;
    Q.push((heapnode){0,s});
    while(!Q.empty())
    {
        heapnode x=Q.top();
        Q.pop();
        int u=x.u;
        if(vis[u]) continue;
        vis[u]=1;
        for(int i=0; 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});
                }
            }
        }
    }
    if(d[0]==INF)
        return 0;
    return 1;
}

intmain ()
{
    int T=0;
    while(~scanf("%d%d",&l,&m)&&l)
    {
        init();
        for(int i=0; i<m; i++)
        {
            char  from [ 25 ], to [ 25 ];
            int dis;
            scanf("%d%s%s",&dis,from,to);
            patch[i].dist=dis;
            for(int j=0; j<l; j++)
            {
                if(from[j]=='+') patch[i].from_has=patch[i].from_has|(1<<j);
                if(from[j]=='-') patch[i].from_no=patch[i].from_no|(1<<j);
                if(to[j]=='+') patch[i].to_has=patch[i].to_has|(1<<j);
                if(to[j]=='-') patch[i].to_no=patch[i].to_no|(1<<j);
            }
        }
        printf("Product %d\n",++T);
        if(dijkstra())
            printf("Fastest sequence takes %d seconds.\n",d[0]);
        else
            printf("Bugs cannot be fixed.\n");
        printf("\n");
    }
}

 

Guess you like

Origin http://43.154.161.224:23101/article/api/json?id=324837990&siteId=291194637