HDU 3001 Travelling

题目描述:

After coding so many days,Mr Acmer wants to have a good rest.So travelling is the best choice!He has decided to visit n cities(he insists on seeing all the cities!And he does not mind which city being his start station because superman can bring him to any city at first but only once.), and of course there are m roads here,following a fee as usual.But Mr Acmer gets bored so easily that he doesn't want to visit a city more than twice!And he is so mean that he wants to minimize the total fee!He is lazy you see.So he turns to you for help.

Input

There are several test cases,the first line is two intergers n(1<=n<=10) and m,which means he needs to visit n cities and there are m roads he can choose,then m lines follow,each line will include three intergers a,b and c(1<=a,b<=n),means there is a road between a and b and the cost is of course c.Input to the End Of File.

Output

Output the minimum fee that he should pay,or -1 if he can't find such a route.

Sample Input

2 1
1 2 100
3 2
1 2 40
2 3 50
3 3
1 2 3
1 3 4
2 3 10

Sample Output

100
90
7 

解题报告:

1:不得不说dp的神奇和强大。下面在2里介绍下数组的作用。

2:g:保存路径。dp[i][j]:核心数组,含义为当前状态i到j城市所花费的最小代价。dic:保存3的n次方。d[i][j]数组:3进制下数字i的第j位是多少。

3:转移方程在下面代码中。下面注释加不加都行,加了可以加快速度。因为dp[i][j]为INF时,不会更新数组的值。

代码:

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const ll N = 15;
const ll NN = 60000;
const ll INF = 0xffffffff;
ll g[N][N], dp[NN][N], dic[N], d[NN][N];
void init(){
    dic[0] = 1;
    for(ll i=1; i<=10; ++i)dic[i] = dic[i-1]*3;
    for(ll i=0; i<dic[10]; ++i){
        ll x = i;
        for(ll j=0; j<10; ++j)d[i][j] = x%3, x /= 3;
    }
}
int main(){
    ll n, m;
    init();
    while(~scanf("%lld%lld", &n, &m)){
        for(ll i=0; i<n; ++i)
            for(ll j=0; j<n; ++j)g[i][j] = INF;
        for(ll i=0; i<dic[n]; ++i)
            for(ll j=0; j<n; ++j)dp[i][j] = INF;
        while(m--){
            ll u, v, val;
            scanf("%lld%lld%lld", &u, &v, &val);
            u--;v--;
            g[u][v] = g[v][u] = min(g[u][v], val);
        }
        for(ll i=0; i<n; ++i)dp[dic[i]][i] = 0;
        ll ans = INF;
        for(ll i=0; i<dic[n]; ++i){
            bool flag = 1;
            for(ll j=0; j<n; ++j){
                if(d[i][j] == 0)flag = 0;
                //if(dp[i][j] == INF)continue;
                for(ll k=0; k<n; ++k){
                    if(g[j][k] == INF || d[i][k] == 2)continue;
                    dp[i+dic[k]][k] = min(dp[i+dic[k]][k], dp[i][j]+g[j][k]);
                }
            }
            if(flag)
                for(ll j=0; j<n; ++j)ans = min(ans, dp[i][j]);
        }
        if(ans == INF)printf("-1\n");
        else printf("%lld\n", ans);
    }
    return 0;
}
发布了206 篇原创文章 · 获赞 9 · 访问量 1万+

猜你喜欢

转载自blog.csdn.net/jun_____/article/details/104299380