UVA - 658_It's not a Bug, it's a Feature! (用map超时,改用位运算完美哈希)

#include<bits/stdc++.h>
using namespace std;
typedef pair<int,string>Pair;

const int maxn = 20 + 3;
const int maxm = 100 + 3;
int n, m;

struct Edge{
    string u, v;
    int w;
    Edge(string u, string v, int w):u(u), v(v), w(w){}
};
vector<Edge>edges;

map<string,int>d;

bool canFix(string &bug, string &patch)
{
    for(int i = 0; i < n; i++){
        if(patch[i] != '0' && patch[i] != bug[i])
            return false;
    }
    return true;
}


int dijkstra()
{
    string source(n, '+');
    string target(n, '-');
    priority_queue<Pair, vector<Pair>, greater<Pair>>pq;
    pq.push(make_pair(0, source));
    d[source] = 0;
    while(!pq.empty()){
        Pair u = pq.top(); pq.pop();
        if(u.second == target){
            return u.first;
        }
        if(u.first != d[u.second]) continue;
        for(int i = 0; i < m; i++){
            if(canFix(u.second, edges[i].u)){
                Pair v(0,u.second);
                for(int j = 0; j < n; j++){
                    if(edges[i].v[j] != '0')
                        v.second[j] = edges[i].v[j];
                }
                if(!d.count(v.second) || d[v.second] > d[u.second] + edges[i].w){
                    d[v.second] = d[u.second] + edges[i].w;
                    v.first = d[v.second];
                    pq.push(v);
                }
            }
        }
    }
    return -1;
}

int main()
{
    //freopen("in.txt", "r", stdin);
    //freopen("out.txt", "w", stdout);
    int kase = 0;
    while(cin >> n >> m && n){
        edges.clear();
        d.clear();
        for(int i = 0; i < m; i++){
            string u, v;
            int w;
            cin >> w >> u >> v;
            edges.push_back(Edge(u, v, w));
        }
        int ans = dijkstra();
        cout << "Product " << ++kase << endl;
        if(ans == -1) cout << "Bugs cannot be fixed.\n";
        else cout << "Fastest sequence takes " << ans << " seconds.\n";
        cout << endl;
    }
    return 0;
}

/*
3 3
1 000 00-
1 00- 0-+
2 0-- -++

4 1
7 0-0-+ ----
*/
View Code

用map超时。

 

 

#include<bits/stdc++.h>
using namespace std;
typedef pair<int,int>Pair;

const int maxn = 20;
const int maxm = 100 + 3;
int n, m;

struct Edge{
    string u, v;
    int w;
    Edge(string u, string v, int w):u(u), v(v), w(w){}
};
vector<Edge>edges;

//map<string,int>d;
int d[1<<maxn];


bool canFix(string &bug, string &patch)
{
    for(int i = 0; i < n; i++){
        if(patch[i] != '0' && patch[i] != bug[i])
            return false;
    }
    return true;
}


int dijkstra()
{
    //string source(n, '+');
    //string target(n, '-');
    priority_queue<Pair, vector<Pair>, greater<Pair>>pq;
    pq.push(make_pair(0, (1<<n)-1));    //2^n - 1,全1即全+,即用1代表+,0代表-,来作为string到int的映射。
    for(int i = 0; i < (1<<n); i++)
        d[i] = INT_MAX;
    d[(1<<n)-1] = 0;
    while(!pq.empty()){
        Pair u = pq.top(); pq.pop();
        if(u.second == 0){
            return u.first;
        }
        if(u.first != d[u.second]) continue;
        for(int i = 0; i < m; i++){
            bool ok = 1;
            for(int j = 0; j < n; j++){
                if(edges[i].u[j] == '+' && !(u.second & (1<<j))){
                    ok = 0; break;
                }else if(edges[i].u[j] == '-' && (u.second & (1<<j))){
                    ok = 0; break;
                }
            }

            if(ok){
                Pair v(0,u.second);
                for(int j = 0; j < n; j++){
                    if(edges[i].v[j] == '+'){   //v的j位设为1
                        v.second |= (1<<j);
                    }else if(edges[i].v[j] == '-'){
                        v.second &= ~(1<<j);
                    }
                }
                if(d[v.second] == INT_MAX || u.first + edges[i].w < d[v.second]){
                    d[v.second] = u.first + edges[i].w;
                    v.first = d[v.second];
                    pq.push(v);
                }
            }
        }
    }
    return -1;
}



int main()
{
//    ios::sync_with_stdio(false);
//    freopen("in.txt", "r", stdin);
//    freopen("out.txt", "w", stdout);
    int kase = 0;
    while(cin >> n >> m && n){
        edges.clear();
        for(int i = 0; i < m; i++){
            string u, v;
            int w;
            cin >> w >> u >> v;
            edges.push_back(Edge(u, v, w));
        }
        int ans = dijkstra();
        cout << "Product " << ++kase << endl;
        if(ans == -1) cout << "Bugs cannot be fixed.\n";
        else cout << "Fastest sequence takes " << ans << " seconds.\n";
        cout << endl;
    }
    return 0;
}

/*
3 3
1 000 00-
1 00- 0-+
2 0-- -++

4 1
7 0-0-+ ----
*/
View Code

位运算完美哈希,AC。

 

收获:

1. 善于利用位运算技巧。比如将某位置一或0。

2. 从题目规模中寻求最好的方法。像这里,n最大为20,百万级别的存储量是可以在全局空间开辟的。

 

posted on 2019-03-15 11:11  nbsanshi  阅读(78)  评论(0编辑  收藏  举报

导航