1048-Provident Housewife

http://rose.u-aizu.ac.jp/onlinejudge/ProblemSet/description.jsp?id=1048&lang=jp
問題概要

考え方
もっと安い値段で買うために、他の店より高い値段で売っている商品は考えないことにする。
また、全ての店に行くことが出来ることから、物が集められないのは、目的のものがどの店でも売っていないときとなる。
後は全ての店の選び方に対して、あらかじめワーシャルフロイド法を使っておき、
循環セールスマン問題として解く。
実装(C++)

#include <cstdio>
#include <cmath>
#include <cstring>
#include <cstdlib>
#include <climits>
#include <cctype>
#include <ctime>
#include <cassert>
#include <cwchar>
#include <cstdarg>
#include <cwctype>
#include <queue>
#include <stack>
#include <algorithm>
#include <list>
#include <vector>
#include <set>
#include <map>
#include <iostream>
#include <deque>
#include <complex>
#include <string>
#include <functional>
using namespace std;
typedef long long int lli;
typedef unsigned int uint;

struct edge{
    int from,to;
    int cost;
    edge(int f,int t,int c){from=f;to=t;cost=c;}
};
struct node:public vector<edge>{
    vector<string> name;
    vector<int> value;
    int buy;
};
typedef vector<node> graph;
const int MAX_V=12;
int d[MAX_V][MAX_V];
int dp[1<<MAX_V][MAX_V];
const int INF=99999999;
int rec(int n,int bit,int s){
    if(dp[bit][s]>=0) return dp[bit][s];
    int res=INF;
    if(bit==(1<<n)-1&&s==0)return dp[bit][s]=0;
    for(int i=0;i<n;i++){
        if(!((bit>> i) &1)){
            res=min(res,rec(n,bit | 1<<i,i)+d[s][i]);
        }
    }
    return dp[bit][s]=res;
}
void warshall_floyd(int n){
    for(int k=0;k<n;k++){
        for(int i=0;i<n;i++){
            for(int j=0;j<n;j++){
                d[i][j]=min(d[i][j],d[i][k]+d[k][j]);
            }
        }
    }
}
void graph2matrix(graph &g){
    int V=g.size();
    for(int i=0;i<V;i++)for(int j=0;j<V;j++)
        if(i==j)d[i][j]=0;else d[i][j]=INF;
    for(int i=0;i<V;i++){
        for(uint j=0;j<g[i].size();j++){
            d[i][g[i][j].to]=g[i][j].cost;
        }
    }
}
int main(){
    for(;;){
        int n;cin >> n;
        if(!n)break;
        map<string,int> min_value;
        graph G(n+1);
        for(int i=1;i<=n;i++){
            int q;cin >> q;string name;int value;
            for(;q--;){
                cin >> name >> value;
                G[i].name.push_back(name);
                G[i].value.push_back(value);
                if(min_value.find(name)!=min_value.end()){
                    min_value[name]=min(min_value[name],value);
                }else{
                    min_value[name]=value;
                }
            }
        }
        int q;vector<string> need;
        int min_v=0;
        cin >> q;
        for(int i=0;i<q;i++){
            string name;
            cin >> name;
            need.push_back(name);
            if(min_value.find(name)!=min_value.end()){
            }else{
                min_v=-1;
            }
        }

        for(int i=1;i<=n;i++){
            G[i].buy=0;
            for(uint j=0;j<G[i].name.size();j++){
                for(int k=0;k<q;k++){
                    if(need[k]==G[i].name[j]){
                        if(G[i].value[j]==min_value[need[k]]){
                            G[i].buy|=1<<k;
                        }
                    }
                }
            }
        }
        int m;
        cin >> m;
        for(int i=0;i<m;i++){
            int a,b,c;
            cin >> a >> b >> c;
            G[a].push_back(edge(a,b,c));
            G[b].push_back(edge(b,a,c));
        }
        //Before Runtime Error
        if(min_v==-1){
            cout << "impossible" << endl;
            continue;
        }


        int minres=INF;
        graph2matrix(G);
        warshall_floyd(n+1);
        //どの店を使うか全通り調べる
        for(int i=0;i<(1<<n);i++){
            int buy=0;
            for(int j=0;j<n;j++){
                if((i>>j)&1){
                    buy|=G[j+1].buy;
                }
            }
            if(buy==(1<<q)-1){
                memset(dp,-1,sizeof(dp));
                minres=min(minres,rec(n+1,((1<<(n+1))-1)^(1+(i<<1)),0));
            }
        }
        min_v=0;
        for(int i=0;i<q;i++){
            min_v+=min_value[need[i]];
        }
        cout << min_v << " "<< minres << endl;
    }

    return 0;
}