洛谷 P1171 售货员的难题

题目描述

某乡有n个村庄( 1

输入输出样例

输入样例#1

3
0 2 1
1 0 2
2 1 0

输出样例#1

3

说明

输入解释

3 {村庄数}

0 2 1 {村庄1到各村的路程}

1 0 2 {村庄2到各村的路程}

2 1 0 {村庄3到各村的路程}

题目分析

这道题大致是两种做法,一种是用搜索,加点剪枝.另一种是用状压DP.(目前还不太会状压DP,所以只讲一下搜索做法,在程序中体现)

程序代码

//这一份是自己写的,暂时不知道问题出在哪.洛谷得分40
#include<iostream>
#include<cstdio>
#include<cstring>
#include<cstring>
#include<algorithm>
using namespace std;
int n,ans=0x3f3f3f3f,f[30],a[30][30],sum=0,mind=0x3f3f3f3f;
void dfs(int k,int u){
    if(k==n+1&&u==1) { ans=min(ans,sum);return ; }
    if(sum>ans) return ;
    for(register int i=1;i<=n;++i){
        if(!f[i]&&i!=u){
            if(sum+a[u][i]+n-k+mind>=ans) return ;
            f[i]=1;sum+=a[u][i];
            dfs(k+1,i);
            f[i]=0;sum-=a[u][i];
        }
    }
}
int main(){
    freopen("P1171.in","r",stdin);
    freopen("P1171.out","w",stdout);
    scanf("%d",&n);
    for(register int i=1;i<=n;++i)
        for(register int j=1;j<=n;++j){
            scanf("%d",&a[i][j]);
            if(i!=1) mind=min(mind,a[i][1]);
        }
    dfs(1,1);
    cout<<ans<<endl;
    return 0;
}

此代码来自以为大佬:
(https://www.luogu.org/blog/user34531/solution-p1171)

#include<iostream>
#include<cstdio> 
#include<algorithm>
using namespace std;
int n,min1=200010,sum,minv[21],mind=200010;
bool vis[21];
struct node{
    int dis,id;
}a[21][21],b[21];
void dfs(int q,int last){
    if(q==n){ min1=min(min1,sum+minv[last]); return ; }
    for(int i=2;i<=n;i++)
        if(!vis[a[last][i].id]){
            if(sum+a[last][i].dis>min1)return;//如果当前已走的距离已经大于当前最优值 返回 
            if(sum+a[last][i].dis+n-q+mind>=min1)return ;
            //假想最小值剩下的村庄(n-q)的距离都是1 并且最后回到1的时候的距离也是最小的。
            //如果此时还是超了当前最小值 后面的就都不需要搜了。 
            vis[a[last][i].id]=1;
            sum+=a[last][i].dis;
            dfs(q+1,a[last][i].id);
            vis[a[last][i].id]=0;
            sum-=a[last][i].dis;
        }
}
bool cmp(node a,node b){return a.dis<b.dis;}
int main(){
    cin>>n;
    for(int i=1;i<=n;i++){
        for(int j=1;j<=n;j++){ cin>>a[i][j].dis; a[i][j].id=j; }
        minv[i]=a[i][1].dis;//minv[i]表示i村庄到1的距离 
        if(i!=1)mind=min(mind,minv[i]);//表示所有村庄到1的最短距离(不包括1到1) 
        sort(a[i]+1,a[i]+n+1,cmp);//读数据时每次得到一行的值后对边值排序。这样可以更快得到较优值。 
    }
    vis[1]=1; dfs(1,1); cout<<min1;
    return 0;
}

猜你喜欢

转载自blog.csdn.net/tangzhide123yy/article/details/80067194