vijos-p1456 2008.11.9
我心得:搜索的优化会有很多种,要从中挑选空间和时间都最优的
描述 Description
n个人在做传递物品的游戏,编号为1-n。
游戏规则是这样的:开始时物品可以在任意一人手上,他可把物品传递给其他人中的任意一位;下一个人可以传递给未接过物品的任意一人。
即物品只能经过同一个人一次,而且每次传递过程都有一个代价;不同的人传给不同的人的代价值之间没有联系;
求当物品经过所有n个人后,整个过程的总代价是多少。
输入格式 Input Format
第一行为n,表示共有n个人(16>=n>=2);
以下为n*n的矩阵,第i+1行、第j列表示物品从编号为i的人传递到编号为j的人所花费的代价,特别的有第i+1行、第i列为-1(因为物品不能自己传给自己),其他数据均为正整数(<=10000)。
(对于50%的数据,n<=11)。
输出格式 Output Format
一个数,为最小的代价总和。
样例输入 Sample Input
2
-19794
2724–1
样例输出 Sample Output
2724
心得:今天终于见识了记忆化搜索,要初始化,何在搜索中的运算。
第一种搜索:80分,改变了搜索顺序,把代价值从小到大排序,从小的开始搜,剪枝的力度还不够,但仍不能ac
program p1456;
type arr=array[1..16,1..2]of longint;
var a:array[1..16]of arr;
ans,i,j,n,max:longint;
f1,f2:text;
b:array[1..16]of boolean;
h:array[1..16]of longint;
procedure qsort(var p:arr);
procedure sort(l,r: longint);
var
i,j,x,y,t1,t2,nn: longint;
begin
i:=l;
j:=r;
nn:=random(j-i+1)+i;
x:=p[nn,1];
repeat
while p[i,1]j) then
begin
y:=p[i,1];
t2:=p[i,2];
p[i,1]:=p[j,1];
p[i,2]:=p[j,2];
p[j,1]:=y;
p[j,2]:=t2;
inc(i);
dec(j);
end;
until i>j;
if lans then exit;
if (t=n+1)and(max
Program2,用到了传说中的记忆化搜索,我没想到,问了别的大牛
program abc;
const maxn=17;
var n:longint;
g:array[0..maxn,0..maxn]of longint;
v:array[0..maxn]of boolean;
tot,ans:longint;
procedure init;
var i,j:longint;
begin
ans:=maxlongint;
fillchar(v,sizeof(v),1);
fillchar(g,sizeof(g),$6f);
readln(n);
for i:=1 to n do
begin
for j:=1 to n do
begin
read(g[i,j]);
if (g[i,j]j) then g[j,0]:=g[i,j];
//这里g[j,0]存放,到达j这个人的最小值,用于以后的剪枝用
end;
end;
end;
procedure try(step,x:longint);
var i,rest:longint;
begin
if step>n then
begin
if tot=ans then exit;//这里用到了刚才的初始化数据,找到还没有到达的节点,在目前的和上累计他们需要的最小代价,如果比当前的最小解ans还大,那就放弃,exit
for i:=1 to n do
if v[i] then
begin
v[i]:=false;
inc(tot,g[x,i]);
try(step+1,i);
v[i]:=true;
dec(tot,g[x,i]);
end;
end;
procedure main;
var i:longint;
begin
for i:=1 to n do
begin
tot:=0;v[i]:=false;
try(2,i);
v[i]:=true;
end;
end;
begin
init;
main;
writeln(ans);
end.