状态压缩的动态规划,设 opt[i][j][s] 表示最后访问的 I,j 各点的遍历情况为 s 的最好值,那么可以更新 opt[j][k][s+2^(k-1)] ,注意 dp 的循序为 s->i->j ,因为 s 更新的为 ss , ss 总是大于 s 的。所以 s 应该从小到大的进行更新。
状态转移方程opt[i][j][s]+v[i]*v[j]*v[k]*map[i][k]+ v[j]*v[k]*map[j][k]+v[k] à opt[j][k][ss]
程序
{
pku2288 Islands and Bridges
By largelymfs
Accepted 44208K 1375MS
Date:2010-05-30 8:06
状态压缩的动态规划
Note:动态规划的枚举顺序
}
program ex;
const
Infile = 'pku2288.in';
Outfile = 'pku2288.out';
maxn = 14;
maxs = 17000;
var
n, m, t: longint;
v: array[0..maxn] of longint;
map: array[0..maxn, 0..maxn] of longint;
opt, way: array[0..maxn, 0..maxn, 0..maxs] of int64;
procedure INit;
var
i, x, y: longint;
begin
Readln(n, m);
for i := 1 to n do
Read(v[i]);
Fillchar(Map, sizeof(Map), $ff);
for i := 1 to n do
map[0][i] := 0;
for i := 1 to m do
begin
Readln(x, y);
map[x][y] := 0;
map[y][x] := 0;
end;
v[0] := 0;
end;
procedure Prepare;
var
i, j, s: longint;
begin
for i := 0 to n do
for j := 0 to n do
for s := 0 to (1 shl n) - 1 do
opt[i][j][s] := -1;
opt[0][0][0] := 0;
Fillchar(way, sizeof(way), 0);
way[0][0][0] := 1;
end;
procedure Main;
var
target, k, s, i, j, ss: longint;
max, now, maxway: int64;
begin
prepare;
for s := 0 to (1 shl n) - 1 do
for i := 0 to n do
for j := 0 to n do
begin
if opt[i][j][s] = -1 then
Continue;
for k := 1 to n do
begin
ss := 1 shl (k - 1);
if (map[j][k] = 0) and (s and ss = 0) then
begin
now := opt[i][j][s] + v[k] + v[j] * v[k];
if map[i][k] = 0 then
now := now + v[i] * v[j] * v[k];
if now = opt[j][k][s + ss] then
begin
way[j][k][s + ss] := way[i][j][s] + way[j][k][s + ss];
end;
if now > opt[j][k][s + ss] then
begin
opt[j][k][s + ss] := now;
way[j][k][ss + s] := way[i][j][s];
end;
end;
end;
end;
target := 1 shl n;
target := target - 1;
max := -1;
maxway := 0;
for i := 1 to n do
for j := 1 to n do
begin
if max = opt[i][j][target] then
maxway := maxway + way[i][j][target];
if max < opt[i][j][target] then
begin
Max := opt[i][j][target];
maxway := way[i][j][target];
end;
end;
if max = -1 then
Writeln(0, ' ', 0)
else
Writeln(max, ' ', maxway div 2);
end;
begin
Assign(Input, Infile);
Reset(input);
Assign(Output, OUtfile);
Rewrite(Output);
Readln(t);
while t > 0 do
begin
Dec(t);
Init;
IF n=1 Then Begin
Writeln(v[1],' ', 1);
end Else Main;
end;
Close(Input);
Close(Output);
end.