【洛谷 1171】售货员的难题

题目描述

某乡有nn个村庄(1<n \le 201<n20),有一个售货员,他要到各个村庄去售货,各村庄之间的路程s(0<s<1000)s(0<s<1000)是已知的,且AA村到BB村与BB村到AA村的路大多不同。为了提高效率,他从商店出发到每个村庄一次,然后返回商店所在的村,假设商店所在的村庄为11,他不知道选择什么样的路线才能使所走的路程最短。请你帮他选择一条最短的路。

输入格式

村庄数nn和各村之间的路程(均是整数)。

输出格式

最短的路程。

输入输出样例

输入 #1
3
0 2 1
1 0 2
2 1 0
输出 #1
3

说明/提示

输入解释

33 {村庄数}

0 2 1021 {村庄11到各村的路程}

1 0 2102 {村庄22到各村的路程}

2 1 0210 {村庄33到各村的路程}

 

题解:我一开始还以为是最短路,后来仔细一看原来是DP

          如果考场的话我会先写全排列拿部分分,再慢慢写状压DP

#include<cstdio>
#include<iostream>
#include<cmath>
#include<cstdlib>
#include<cstring>
#include<algorithm>
#include<bits/stdc++.h>
typedef long long ll;
using namespace std;
const int oo=0x3f3f3f3f;
int ans=oo,n,a[22][22],f[1100011][21];
int main(){
    freopen("1171.in","r",stdin);
    freopen("1171.out","w",stdout);
    scanf("%d",&n);
    for(int i=0;i<n;i++)
        for(int j=0;j<n;j++)
            scanf("%d",&a[i][j]);
    memset(f,0x3f,sizeof(f));
    f[1][0]=0;
    int mx=1<<n;
    for(int s=0;s<mx;s++){
        for(int i=0;i<n;i++){
            if(f[s][i]==oo) continue;//i位为1才可推过来 
            for(int j=0;j<n;j++){
                if(((s>>j)&1)==0){//j位为0 
                    int now=s|(1<<j);
                    f[now][j]=min(f[now][j],f[s][i]+a[i][j]);
                }
            }
        }
    }
    for(int i=0;i<n;i++)
        ans=min(ans,f[(1<<n)-1][i]+a[i][0]);
    cout<<ans;
    return 0;
}

 

posted @ 2020-11-02 20:04  #Cookies#  阅读(113)  评论(0编辑  收藏  举报