Description
某乡有 个村庄 ,有一个售货员,他要到各个村庄去售货,各村庄之间的路程 是已知的,且 村与 村与 村与 村的路大多不同,为了提高效率,他从商店出发到每个村庄一次,然后返回商店所在的村,假设商店所在的村庄为 ,他不知道选择什么样的路才能使所走的路程最短,请你帮助他选择一条路径。
Input
村庄数 和各村之间的路程(均是整数)
Output
最短路程
Sample Input
3 // 村庄数量
0 2 1 // 村庄 1 到各村的路程
1 0 2
2 1 0
Sample Output
3
解题思路
企图多用一个剪枝,然后把自己剪死了。。。:)
暴力深搜从 走回 的情况,记录有没有遍历过所有点。
因为每个村庄只走一次,so往回走的时候,直接利用邻接矩阵
这条路。
但是,我用邻接表,企图利用在,这一题里每条链第一个点必定是
的特性,找到
这条路,发现我wa了。。。:)
假设剩下的点之间通过的路全是1,这种最小情况下,目前求的答案还是大于已求出答案,就可以剪掉。
很好,这个剪枝我没错(欢呼雀跃!!!)
#include<iostream>
#include<cstdio>
using namespace std;
struct DT{
int to,s,next;
}a[2000];
int head[50],n,v[50],num,Gun=10000;
int demo(int sum,int x){//上述的第一个剪枝,不知为何就是错了
int i;
for(i=head[x];a[i].next;i=a[i].next);
return (sum+a[i].s);
}
void DFS(int dep,int x,int sum){
if(dep>n){
Gun=min(Gun,sum);
return;
}
/*上面我原本打的是
if(dep==n){
Gun=min(Gun,demo(sum,x));
return;
}
*/
if(v[1]==1)return;//不加上就wa了
if(sum+(n-dep+1)>Gun)return;//上述的第二个剪枝
for(int i=head[x];i;i=a[i].next){
if(!v[a[i].to]){
v[a[i].to]=1;//v标记走没走过
DFS(dep+1,a[i].to,sum+a[i].s);
v[a[i].to]=0;
}
}
}
int main(){
scanf("%d",&n);
for(int i=1;i<=n;i++)
for(int j=1;j<=n;j++){
int x;
scanf("%d",&x);
if(x){
a[++num].s=x,a[num].to=j,a[num].next=head[i],head[i]=num;//建邻接表
Gun+=a[num].s;//这个Gun是最终答案,至于为什么要加这些乱七八糟的,是因为我忘记无限大怎么打了。。。
}
}
DFS(1,1,0);
printf("%d",Gun);
}