• oil倒油


    skysun原创,转载请注明出处。

    http://www.cnblogs.com/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所以可以开大些}


  • 相关阅读:
    Quartz.net 定时任务在IIS中未按时执行
    扩展方法
    mysql 实用语句
    jquery each map
    js匿名函数多时注意
    ASP.NET MVC3调用分部视图
    eclipse快捷键
    regular 点滴
    适配器模式
    php代码实现简单图片下载
  • 原文地址:https://www.cnblogs.com/skysun/p/2411383.html
Copyright © 2020-2023  润新知