洛谷P1171 售货员的难题

P1171 售货员的难题

题目背景

数据有更改

题目描述

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

输入输出格式

输入格式:

 

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

 

输出格式:

 

最短的路程。

 

输入输出样例

输入样例#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到各村的路程}

/*
    洛谷上只能到90分qwq
*/
#include<iostream>
#include<cstdio>
#define maxn 20
int n,num,head[maxn],ans=0x7fffffff;
struct node{
    int to,pre,v;
}e[maxn*maxn];
bool vis[maxn];
using namespace std;
void Insert(int from,int to,int v){
    e[++num].to=to;
    e[num].v=v;
    e[num].pre=head[from];
    head[from]=num;
}
void dfs(int pos,int cnt,int dis){
    if(dis>=ans)return;
    if(dis+n-cnt+1>=ans)return;
    for(int i=head[pos];i;i=e[i].pre){
        int to=e[i].to;
        if(to==1&&cnt==n){
            ans=min(ans,dis+e[i].v);
            return;
        }
        if(vis[to])continue;
        vis[to]=1;
        dfs(to,cnt+1,dis+e[i].v);
        vis[to]=0;
    }
}
int qread(){
    int i=0;
    char ch=getchar();
    while(ch<'0'||ch>'9')ch=getchar();
    while(ch<='9'&&ch>='0'){i=i*10+ch-'0';ch=getchar();}
    return i;
}
int main(){
    freopen("Cola.txt","r",stdin);
    n=qread();
    int x;
    for(int i=1;i<=n;i++)
        for(int j=1;j<=n;j++){
            x=qread();
            if(i!=j)Insert(i,j,x);
        }
    vis[1]=1;
    dfs(1,1,0);
    printf("%d",ans);
}
90分 搜索+剪枝
#include<iostream>
#include<cstdio>
#include<cstring>
using namespace std;
int n,map[21][21],all,dp[21][1<<20],ans=0x7fffffff;
int qread(){
    int i=0;
    char ch=getchar();
    while(ch<'0'||ch>'9')ch=getchar();
    while(ch<='9'&&ch>='0'){i=i*10+ch-'0';ch=getchar();}
    return i;
}
int main(){
    freopen("Cola.txt","r",stdin);
    //scanf("%d",&n);
    n=qread();
    all=(1<<n)-1;
    for(int i=1;i<=n;i++)for(int j=1;j<=n;j++)map[i][j]=qread();
    memset(dp,0x3f,sizeof(dp));
    dp[0][0]=0;
    for(int i=1;i<=n;i++)dp[i][1<<(i-1)]=map[1][i];
    for(int s=0;s<=all;s++){
        for(int i=1;i<=n;i++)
            if(s&(1<<(i-1)))
                for(int j=1;j<=n;j++)
                    dp[i][s]=min(dp[i][s],dp[j][s^(1<<(i-1))]+map[j][i]);
    }
    for(int i=1;i<=n;i++)ans=min(ans,dp[i][all]+map[i][1]);
    printf("%d",ans);
}
80分 状压+枚举
#include<iostream>
#include<cstdio>
#include<cstring>
#define min(a,b) (a)>(b)?(b):(a)
int n,map[21][21],all,dp[21][1<<20],ans=0x7fffffff,bit[21];
int qread(){
    int i=0;
    char ch=getchar();
    while(ch<'0'||ch>'9')ch=getchar();
    while(ch<='9'&&ch>='0'){i=i*10+ch-'0';ch=getchar();}
    return i;
}
int main(){
    freopen("Cola.txt","r",stdin);
    //scanf("%d",&n);
    bit[1]=1;
    for(int i=2;i<=20;i++)bit[i]=bit[i-1]<<1;
    n=qread();
    all=(1<<n)-1;
    for(int i=1;i<=n;i++)for(int j=1;j<=n;j++)map[i][j]=qread();
    memset(dp,0x3f,sizeof(dp));
    dp[1][1]=0;
    for(int s=1;s<=all;s+=2){
        for(int i=1;i<=n;i++)
            if(dp[i][s]<=30000)
                for(int j=1;j<=n;j++)
                if(!(s&bit[j]))
                    dp[j][s|bit[j]]=min(dp[j][s|bit[j]],dp[i][s]+map[i][j]);
    }
    for(int i=1;i<=n;i++)ans=min(ans,dp[i][all]+map[i][1]);
    printf("%d",ans);
}
100分 状压

 

posted @ 2017-10-24 17:05  Echo宝贝儿  阅读(500)  评论(0编辑  收藏  举报