2.pizza
描述:
Dsqwwe从小到大都没有吃过披萨,今天,他终于忍不住了,于是他叫了一份必胜客的外卖,由于不是dsqwwe一个人叫外卖,送外卖的小哥要到每个叫外卖的顾客家中然后最后回到必胜客…..这里有n-1个顾客叫外卖,必胜客在1号路口,叫外卖的顾客家分别在2,3,4…..n号路口,每两个路口都有一条通路,小哥想保证送外卖的时间最少,问最少时间为多少(一个路口可以多次经过的)
输入:
第一行:n(2<=n<=15)
接下来n行每行n个数,第i行第j列代表从i到j的时间,当然这个矩阵是沿对角线对称的,且i行i列为0,除此外都不为0
输出:
最少时间
样例输入:pizza
4
0 1 10 10
1 0 1 2
10 1 0 10
10 2 10 0
样例输出:
8
状态压缩 DP +记忆化搜索。
首先用 f[i,j] 表示当走到了 j 状态,(二进制),最后一个走的是 i 时,最少的时间。
然后,搜索。
每次,枚举 j=1<<(n-1)-1 时,也就是全走完时的 i ,然后倒着往前,依次枚举着,记忆化着搜,每一次如果枚举到第一个,且解比当前最优解好,就更新。
然后就是这样。
注意最后要走回到起点。
program liukeke;
var
map:array[0..16,0..16] of longint;
f:array[0..16,0..32770] of longint;
n:longint;
i,j,k,ans:longint;
procedure init;
var
i,j:longint;
begin
fillchar(map,sizeof(map),127);
readln(n);
for i:=1 to n do
for j:=1 to n do
read(map[i,j]);
end;
procedure floyd;
var
i,j,k:longint;
begin
for k:=1 to n do
for i:=1 to n do
if i<>k then
for j:=1 to n do
if (i<>j)and(j<>k) then
if map[i,j]>map[i,k]+map[k,j] then
map[i,j]:=map[i,k]+map[k,j];
end;
function dfs(now,t:longint):longint;
var
i,temp:longint;
begin
if f[now,t]<maxlongint then exit(f[now,t]);
if t=0 then
begin
f[now,t]:=map[1,now+1];
exit(f[now,t]);
end;
for i:=1 to n-1 do
begin
if (t and (1<<(i-1)) )=0 then continue;
temp:=t-(1<<(i-1));
if dfs(i,temp)+map[i+1,now+1]<f[now,t] then
f[now,t]:=dfs(i,temp)+map[i+1,now+1];
end;
exit(f[now,t]);
end;
begin
assign(input,'pizza.in');reset(input);
assign(output,'pizza.out');rewrite(output);
init;
floyd;
//dp;
ans:=maxlongint;
for i:=1 to n-1 do
for j:=0 to 1<<(n-1) do
f[i,j]:=maxlongint;
for i:=1 to n-1 do
begin
k:=(1<<(n-1)-1)-(1<<(i-1));
if dfs(i,k)+map[i+1,1]<ans then ans:=dfs(i,k)+map[i+1,1];
end;
writeln(ans);
close(input);
close(output);
end.