贪婪的Copy

题目描述

Copy从卢牛那里听说在一片叫yz的神的领域埋藏着不少宝藏,于是Copy来到了这个被划分为个区域的神地。卢牛告诉了Copy这里共有个宝藏,分别放在第Pi个(1<=Pi<=N)区域。Copy还得知了每个区域之间的距离。现在Copy从1号区域出发,要获得所有的宝藏并到n号区域离开。Copy很懒,只好来找你为他寻找一条合适的线路,使得他走过的距离最短。

输入输出格式

输入格式:

第一行一个正整数N(1<=N<=100)

接下来一个N*N的矩阵,第i+1行第j列的数字表示区域i,j之间的距离。每个距离用空格隔开,距离保证i,j<=1000。请注意的i to j距离并不一定等于j to i的距离。

第N+2行一个整数P(0<=P<=10)。

第N+3行共P个用空格隔开的整数,表示有宝藏的区域编号。

输出格式:

一个整数,为Copy获得全部宝藏需要的最短距离。数据保证答案小于等于maxlongint。

输入输出样例

输入样例#1: 复制
样例输入1
2
0 4
5 0
2
1 2

样例输入2
3
0 2 6
1 0 4
7 10 0
1
2
输出样例#1: 复制
样例输出1
4

样例输出1
6

说明

对30%的数据,1<=n<=15,其余如题所述。

对100%的数据,全部数据范围如题所述。

Solution:先Floyd找出最短路,再枚举每一种寻宝方式即可。

#include<bits/stdc++.h>
#define REP(i, a, b) for(int i = (a); i <= (b); ++ i)
#define REP(j, a, b) for(int j = (a); j <= (b); ++ j)
#define PER(i, a, b) for(int i = (a); i >= (b); -- i)
#define REP(k, a, b) for(int k = (a); k <= (b); ++ k)
using namespace std;
const int maxn=105;
template <class T>
inline void rd(T &ret){
    char c;
    ret = 0;
    while ((c = getchar()) < '0' || c > '9');
    while (c >= '0' && c <= '9'){
        ret = ret * 10 + (c - '0'), c = getchar();
    }
}
int n,dis[maxn][maxn],w[maxn],p,ans;
int main()
{
    memset(dis,127,sizeof(dis));
    ans=0x3f3f3f3f;
    rd(n);
    REP(i,1,n){
       REP(j,1,n){
           rd(dis[i][j]);
       }
    }
    rd(p);
    REP(i,1,p)rd(w[i]);
    REP(k,1,n){
       REP(i,1,n){
          REP(j,1,n){
             dis[i][j]=min(dis[i][j],dis[i][k]+dis[k][j]);
          }
       }
    }
    sort(w+1,w+1+p);
    do{
        int tmp=0;
        tmp=dis[1][w[1]]+dis[w[p]][n];
        REP(i,1,p-1)tmp+=dis[w[i]][w[i+1]];
        ans=min(ans,tmp);
    }while(next_permutation(w+1,w+1+p));
    cout<<ans<<endl;
    return 0;
}
原文地址:https://www.cnblogs.com/czy-power/p/10449599.html