题目描述
某乡有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;
}