skysun原创,转载请注明出处。
题目大意
一、 分油问题(oil.pas)。
设有大小不等的3个无刻度的油桶,分别能盛满X、Y、Z(都小于等于100)升油,初始时其中一个油桶盛满,另外两个为空。现在,要想分出T升油。分油时可把一个桶里的油倒入另外的桶中。设计一种以最少步骤的分油方案。
输入:以文件方式输入数据,格式为:
第一行:X Y Z {设一个油桶已装满油}
第二行:T {要分出的目标油量}
输出:所需要的步数{原题不是输出步数,由于评测问题……改简单了}
很明显是一道搜索题
方法一:bfs
一般来说,求最小步数都应该用宽搜来解,因为一旦出解就输出,并且一定是最优解;
宽搜需要注意一些赋初值问题,尤其是多遍搜索,不是改一个h,t就可以,最基本的布尔数组得改,这也一般忘不了
还有记录是否更新ans的变量,盛放队列里每个结点的步数的数组(只需F[0]=0就可以)
再就是,也是很重要的一点,就是需要用数组储存每个状态的3个油桶的油量,虽然很简单
但是很重要,不然的话,不利用数组的有序性,直接写转移,会繁琐很多
BFS
1 program sky;
2 const
3 maxn = 1000000;
4 maxq = 1000000;
5 var
6 flag : boolean;
7 i,j,k : longint;
8 h,t,tar,ans,tp : longint;
9 f : array[0..maxq+1] of longint;
10 v : array[0..301,0..301,0..301] of boolean;
11 q : array[0..maxq+1,1..3] of longint;
12 c : array[0..3] of longint;
13 procedure bfs(x : longint );
14 begin
15 fillchar(v,sizeof(v),0);
16 h:=1; t:=1; tp:=maxn; flag:=false; f[1]:=0;
17 for i:=1 to 3 do
18 if i=x then q[1,i]:=c[i] else q[1,i]:=0;
19 while h<>t+1 do
20 begin
21 for i:=1 to 3 do
22 for j:=1 to 3 do
23 if (i<>j) and (q[h,i]>0) and (q[h,j]<c[j]) then
24 begin
25 inc(t); if t=maxq then t:=1;
26 f[t]:=f[h]+1;
27 for k:=1 to 3 do q[t,k]:=q[h,k];
28 if c[j]-q[h,j]<q[h,i] then
29 begin
30 q[t,i]:=q[h,i]-(c[j]-q[h,j]);
31 q[t,j]:=c[j];
32 end else
33 begin
34 q[t,j]:=q[h,j]+q[t,i];
35 q[t,i]:=0;
36 end;
37 if v[q[t,1],q[t,2],q[t,3]] then dec(t);
38 if t=0 then t:=maxq-1;
39 v[q[t,1],q[t,2],q[t,3]]:=true;
40 if (q[t,1]=tar) or (q[t,2]=tar) or (q[t,3]=tar) then
41 begin
42 flag:=true;
43 tp:=f[t];
44 break;
45 end;
46 end;
47 if flag then break;
48 inc(h);
49 end;
50 if tp<ans then ans:=tp;
51 end; { bfs }
52
53 begin
54 assign(input,'oil.in'); reset(input);
55 assign(output,'oil.out'); rewrite(output);
56 readln(c[1],c[2],c[3]);
57 readln(tar);
58 ans:=maxn;
59 bfs(1); bfs(2); bfs(3);
60 if ans=maxn then writeln('NO ANSWER!') else writeln(ans);
61 close(input); close(output);
62 end.
方法二:迭代加深dfs
我不是很擅长打dfs,所以一开始就打的bfs,后来发现这也能过
不过最坑人的地方是,dfs这个过程里若开一个小数组而不是变量,速度会慢很多,
至于循环范围(迭代深度)完全是边测试边调整,直到不超时为止……
其实过程里可能有错,因为我是看的同学的程序,他的到1500都没问题,我的50就超时了,
若有大牛发现,麻烦指正,邮箱 leaf_and_me@126.com
这样也能出解
注意点和bfs差不多
DFS
1 program sky;
2 type
3 aa = array[1..3] of longint;
4 var
5 ans,tar : longint;
6 b,c : aa;
7 v : array[0..100,0..100,0..100] of boolean;
8
9 procedure print(x :longint );
10 begin
11 writeln(x);
12 close(input); close(output);
13 halt;
14 end;
15 procedure dfs(b : aa;x:longint );
16 var
17 i,j,z : longint;
18 d : aa;
19 begin
20 if x>ans then exit;
21 if (b[1]=tar) or (b[2]=tar) or (b[3]=tar) then print(x);
22 d:= b;
23 for i:=1 to 3 do
24 for j:=1 to 3 do
25 if (i<>j) and (b[i]>0) and (b[j]<c[j]) then
26 begin
27 if b[i]>c[j]-b[j] then
28 begin
29 b[i]:=b[i]-(c[j]-b[j]);
30 b[j]:=c[j];
31 end else
32 begin
33 b[j]:=b[j]+b[i];
34 b[i]:=0;
35 end;
36 if not v[b[1],b[2],b[3]] then
37 begin
38 v[b[1],b[2],b[3]]:=true;
39 dfs(b,x+1);
40 end;
41 b:=d;
42 end;
43 end;
44 begin
45 assign(input,'oil.in'); reset(input);
46 assign(output,'oil.out'); rewrite(output);
47 readln(c[1],c[2],c[3]);
48 readln(tar);
49 for ans:=1 to 10 do
50 begin
51 b[1]:=c[1]; b[2]:=0; b[3]:=0;
52 fillchar(v,sizeof(v),0); v[b[1],b[2],b[3]]:=true;
53 dfs(b,0);
54 b[1]:=0; b[2]:=c[2]; b[3]:=0;
55 fillchar(v,sizeof(v),0); v[b[1],b[3],b[3]]:=true;
56 dfs(b,0);
57 b[1]:=0; b[2]:=0; b[3]:=c[3];
58 fillchar(v,sizeof(v),0); v[b[1],b[2],b[3]]:=true;
59 dfs(b,0);
60 end;
61 writeln('NO ANSWER!');
62 close(input); close(output);
63 end.
{最新修改:已改正,速度慢是因为v数组开的太大,fillchar太费时间,宽搜由于仅进行2-3次fillchar所以可以开大些}