【状压DP】售货员的难题
2013-03-03 16:23
183 查看
售货员的难题
【问题描述】
某乡有n个村庄(1<n<=13),有一个售货员,他要到各个村庄去售货,各村庄之间的路程s(0<s<1000)是已知的,且A村到B村与B村到A村的路大多不同。为了提高效率,他从商店出发到每个村庄一次,然后返回商店所在的村,假设商店所在的村庄为1,他不知道选择什么样的路线才能使所走的路程最短。请你帮他选择一条最短的路。
【输入】
村庄数n和各村之间的路程(均是整数)。
【输出】
最短的路程。
【样例】
salesman.in salesman.out
3 {村庄数} 3
0 2 l {村庄1到各村的路程}
1 0 2 {村庄2到各村的路程}
2 1 0 {村庄3到各村的路程}
本来是搜索练习题,看一个学长把它做成了状压DP,于是我也来试试
用 f [ i ] [ S ] 表示当前到达 i 号点,状态为 S 的最短路,最终我们只需在所有的 f [ i ] [ all ] + map [ i ] [ 1 ] 中找一个最大值即可,all为全为1的01序列
用0表示没走过,1表示走过
那么比如状态S=111,就可以从1号点110,或2号点101,或3号点011走来,这样转移方程就出来了
f [ i ] [ S ] = m i n ( f [ i ] [ S ] , f [ j ] [ S & ( ~ ( 1 < < i ) ) ] ) ;
做了几道状压DP后再来做这一题,感觉容易多了~
这一题搜索有几组3秒都跑不过,但是DP秒过!
C++ AC Code
#include<cstdio>
#include<algorithm>
using namespace std;
int n,map[20][20];
int f[20][1<<15];
int main()
{
freopen("salesman.in","r",stdin);
freopen("salesman.out","w",stdout);
scanf("%d",&n);
for(int i=0;i<n;i++)
for(int j=0;j<n;j++)
scanf("%d",&map[i][j]);
int all=(1<<n)-1;
memset(f,0x3f,sizeof(f));
f[0][0]=0;
for(int i=0;i<n;i++) f[i][1<<i]=map[0][i];
for(int S=0;S<=all;S++)
for(int i=0;i<n;i++)
for(int j=0;j<n;j++)
if(map[j][i]>0 && (S&(1<<i))!=0)
f[i][S]=min(f[i][S],f[j][S&(~(1<<i))]+map[j][i]);
int res=0x3f3f3f3f;
for(int i=0;i<n;i++) res=min(res,f[i][all]+map[i][0]);
printf("%d\n",res);
return 0;
}
源程序名 salesman.???(pas, c, cpp) 可执行文件名 salesman.exe 输入文件名 salesman.in 输出文件名 salesman.out |
某乡有n个村庄(1<n<=13),有一个售货员,他要到各个村庄去售货,各村庄之间的路程s(0<s<1000)是已知的,且A村到B村与B村到A村的路大多不同。为了提高效率,他从商店出发到每个村庄一次,然后返回商店所在的村,假设商店所在的村庄为1,他不知道选择什么样的路线才能使所走的路程最短。请你帮他选择一条最短的路。
【输入】
村庄数n和各村之间的路程(均是整数)。
【输出】
最短的路程。
【样例】
salesman.in salesman.out
3 {村庄数} 3
0 2 l {村庄1到各村的路程}
1 0 2 {村庄2到各村的路程}
2 1 0 {村庄3到各村的路程}
本来是搜索练习题,看一个学长把它做成了状压DP,于是我也来试试
用 f [ i ] [ S ] 表示当前到达 i 号点,状态为 S 的最短路,最终我们只需在所有的 f [ i ] [ all ] + map [ i ] [ 1 ] 中找一个最大值即可,all为全为1的01序列
用0表示没走过,1表示走过
那么比如状态S=111,就可以从1号点110,或2号点101,或3号点011走来,这样转移方程就出来了
f [ i ] [ S ] = m i n ( f [ i ] [ S ] , f [ j ] [ S & ( ~ ( 1 < < i ) ) ] ) ;
做了几道状压DP后再来做这一题,感觉容易多了~
这一题搜索有几组3秒都跑不过,但是DP秒过!
C++ AC Code
#include<cstdio>
#include<algorithm>
using namespace std;
int n,map[20][20];
int f[20][1<<15];
int main()
{
freopen("salesman.in","r",stdin);
freopen("salesman.out","w",stdout);
scanf("%d",&n);
for(int i=0;i<n;i++)
for(int j=0;j<n;j++)
scanf("%d",&map[i][j]);
int all=(1<<n)-1;
memset(f,0x3f,sizeof(f));
f[0][0]=0;
for(int i=0;i<n;i++) f[i][1<<i]=map[0][i];
for(int S=0;S<=all;S++)
for(int i=0;i<n;i++)
for(int j=0;j<n;j++)
if(map[j][i]>0 && (S&(1<<i))!=0)
f[i][S]=min(f[i][S],f[j][S&(~(1<<i))]+map[j][i]);
int res=0x3f3f3f3f;
for(int i=0;i<n;i++) res=min(res,f[i][all]+map[i][0]);
printf("%d\n",res);
return 0;
}
相关文章推荐
- 洛谷P1171 售货员的难题【状压DP】
- 洛谷 P1171 售货员的难题 【状压dp】
- 洛谷 P1171 售货员的难题 【状压dp】
- 售货员难题 状压dp
- 洛谷 1171 售货员的难题 状压DP 解题报告
- 【codevs2596】售货员的难题 状压DP
- [LSGDOJ 1505]售货员的难题 状压DP
- 2596 售货员的难题[状态压缩&&优先队列]
- [swustoj 411] 售货员的难题
- 洛谷P1171 售货员的难题
- Luogu 1171 售货员的难题(状态压缩动态规划)
- 售货员的难题(0411)
- 售货员的难题(codevs 2596)
- CODEVS 2596 售货员的难题
- 售货员的难题(0411)
- 售货员的难题
- P1171 售货员的难题
- caioj1041:递归11(售货员的难题)
- 售货员的难题
- 洛谷P1171 售货员的难题