poj 3311 Hie with the Pie floyd+状态压缩dp
题目大意
给你n个城市(1~n)和一个PIZZA店(0),要求找一条回路,从0出发,又回到0,而且距离最短。
分析
先用floyd把任意I,j两点的最短路找出来。
再DP:
D[I,j]=min(d[I,j],d[i xor (1 shl (j-1)),k]+f[k,j])((i and (1 shl (j-1)))<>0)(1<=j,k<=n)
其中i表示用二进制表示n个城市,1表示经过,0表示没有经过。F表示k到j的最短路。
结果即为min(d[1 shl n-1][j]+f[j][0]){因为还要回点0}
代码
var f:array[0..100,0..100] of longint; d:array[0..5000,0..100] of longint; c:array[0..100] of longint; i,j,k,l:longint; n:longint; ans:longint; begin readln(n); while n<>0 do begin for i:=0 to n do begin for j:=0 to n do read(f[i,j]); readln; end; for k:=0 to n do for i:=0 to n do for j:=0 to n do if (i<>j) and (i<>k) and (j<>k) then if f[i,k]+f[k,j]<f[i,j] then f[i,j]:=f[i,k]+f[k,j]; fillchar(d,sizeof(d),$7f); d[0][1]:=0; for i:=0 to 1 shl n-1 do begin for j:=1 to n do begin if i=1 shl (j-1) then d[i][j]:=f[0][j]; if (i and (1 shl (j-1)))<>0 then begin l:=i xor (1 shl (j-1)); for k:=1 to n do if (l and (1 shl (k-1)))<>0 then if d[l][k]+f[k,j]<d[i][j] then d[i][j]:=d[l][k]+f[k,j]; end; end; end; ans:=maxlongint; for i:=1 to n do if ans>d[1 shl n-1][i]+f[i][0] then ans:=d[1 shl n-1][i]+f[i][0]; writeln(ans); readln(n); end; end.