您的位置:首页 > 其它

解题报告 Pizza

2011-11-05 19:48 225 查看

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.
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: