658 - It's not a Bug, it's a Feature! (Dijkstra算法)

今天第一次系统的学习了一下最短路算法,开始刷第十一章,第一次写Dijkstra算法,出现了很多喜闻乐见的错误。。而且uva上样例很水,瓢虫也很水 ,坑了我好久。

首先是对于结点的处理,我们必须要维护一个二元组,一个表示结点一个表示当前结点最短路。   因为Dijkstra算法利用了优先队列来加速算法,所以需要定义小于运算符,一开始我直接将状态装进了优先队列,显然是不对的,因为优先队列的作用就是取出当前距离最短的结点。

其次,说说最短路算法蕴含的巧妙思想: 每次从当前所有还未标记的结点中选择一个距离最小的点,从这个点更新与之相连的所有结点 。重复此过程 。 

为什么这样做是正确的呢? 百度百科上有一个动态图可以帮助我们很好的理解这个过程 。传送门:点击打开链接

该题是一个很巧妙的最短路问题,需要我们把模型抽象出来,看清楚要解决的问题的实质是什么。

该题是复杂状态的最短路问题,需要将状态抽象出来当做结点 。 

将状态集合当做结点,将所花费的时间当做边的权值,两个“结点”是否相连取决于第一个字符串与该结点的关系! 真是好题 ~

另外一点,用动态规划进行状态转移时很重要的一点是不能转移到以前的状态,即状态图不是DAG,所以不能用记忆化搜索 。 

细节参见代码:

#include<bits/stdc++.h>
using namespace std;
const int INF = 0x3f3f3f3f;
const int maxn = 22;
const int maxm = 105;
int n,m,kase = 0,ok = 0 ,d[1<<maxn],done[1<<maxn];
struct node{
    int t;
    char a[maxn],b[maxn];
}pat[maxm];
struct Node{
    int bugs,dist;
    bool operator < (const Node& v) const {
        return dist > v.dist;
    }
};
int dijkstra() {
    priority_queue<Node> q;
    for(int i=0;i<(1<<n);i++) { done[i] = 0; d[i] = INF; }
    Node u; u.dist = 0; u.bugs = (1<<n)-1;
    d[u.bugs] = 0;
    q.push(u);
    while(!q.empty()) {
        Node u = q.top(); q.pop();
        if(u.bugs == 0) return u.dist;
        if(done[u.bugs]) continue;
        done[u.bugs] = true;
        for(int i=1;i<=m;i++) {
            bool ok = true;
            for(int j=0;j<n;j++) {  //检查该结点是否可以连一条边
                if(pat[i].a[j] == '-' && u.bugs & (1<<j)) { ok = false; break; } 
                if(pat[i].a[j] == '+' && !(u.bugs & (1<<j))) { ok = false; break; }
            }
            if(ok) {
                Node v = u ;
                for(int j=0;j<n;j++) { //更新找到下一个结点
                    if(pat[i].b[j] == '-') {
                         v.bugs &= ~(1<<j);
                    }
                    else if(pat[i].b[j] == '+') {
                        v.bugs |= (1<<j);
                    }
                }
                if(d[v.bugs] > u.dist + pat[i].t) {
                    d[v.bugs] = u.dist + pat[i].t;
                    v.dist = d[v.bugs];
                    q.push(v);
                }
            }
        }
    }
    return -1;
}
int main() {
    while(~scanf("%d%d",&n,&m)) {
        if( !n && !m ) return 0;

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


你可能感兴趣的:(算法,ACM,dijkstra,uva,ACM-ICPC)