传送门
http://codevs.cn/problem/2800/
题目大意
给定n个点间的距离的邻接矩阵,询问从0出发走过所有点再回到0的最短距离,1个点可以多次访问
题解
状压DP
dp[i,j]:i表示状态,j表示该状态下最后访问的点
var
w:array[0..20,0..20]of longint;
dp:array[0..42000,0..20]of longint;
i,j,k:longint;
n,ans:longint;
function min(a,b:longint):longint;
begin
if a>b then exit(b) else exit(a);
end;
begin
readln(n);
for i:=0 to n do
for j:=0 to n do
read(w[i,j]);
for k:=0 to n do
for i:=0 to n do
for j:=0 to n do
w[i,j]:=min(w[i,k]+w[k,j],w[i,j]);
for i:=1 to 1<<n-1 do
for j:=0 to n do
dp[i,j]:=1000000000;
dp[0,0]:=0;
for i:=1 to (1<<n)-1 do
for j:=0 to n do
begin
if (j<>0)and(i and (1<<(j-1))=0) then continue;
for k:=0 to n do
begin
if (j=k)or((k<>0)and(i and (1<<(k-1))=0)) then continue;
dp[i,j]:=min(dp[i,j],dp[i,k]+w[k,j]);
if j<>0 then dp[i,j]:=min(dp[i,j],dp[i-(1<<(j-1)),k]+w[k,j]);
end;
end;
ans:=maxlongint;
for i:=1 to n do
if ans>dp[1<<n-1,i]+w[i,0] then ans:=dp[1<<n-1,i]+w[i,0];
writeln(ans);
end.