zoukankan      html  css  js  c++  java
  • POJ3414Pots

    转载请注明出处:優YoU http://user.qzone.qq.com/289065406/blog/1303732259

    题目大意:

    给出了两个瓶子的容量A,B, 以及一个目标水量C

    AB可以有如下操作:

    FILL(i)        fill the pot i (1 ≤ i ≤ 2) from the tap;

    DROP(i)      empty the pot i to the drain;

    POUR(i,j)    pour from pot i to pot j; after this operation either the pot j is full (and there may be some water left in the pot i), or the pot i is empty (and all its contents have been moved to the pot j).

    问经过哪几个操作后能使得任意一个瓶子的残余水量为C

    若不可能得到则输出impossible

     

     

     

    解题思路:
    6
    入口的bfs

    把两个两个桶的某个同一时间的状态看做一个整体,视为初态

    可对初态进行六种操作,即FILL(1),FILL(2),DROP(1),DROP(2),POUR(1,2),POUR(2,1)

    6种操作在我的程序中分别用一个整数进行记录;

    1z0: 清空z瓶子

    2z0: 装满z瓶子

    3xy: x瓶倒向y

    x,y,z{1,2}

    这样在输出操作时就能根据数字的特点 进行选择性输出

     

     

    这题有两个难点:

    第一就是要输出得到容量C的过程。

    对于BFS的题而言这种要求是非常刁钻的,回溯每一步时很容易就混淆了下标。

    解决方法:对于每一步的操作,我们都得对它设置一个pos指针,使它指向前一步操作在queue[]队列的下标,即对下标进行回溯,再顺序输出每一步操作

     

    第二就是状态记录。怎样记录两个瓶子在同一时间点的状态,又能使得搜索标记时为O(1)的复杂度?

    瓶子某时刻的残余水量就是该瓶子的状态,设残余水量为k1 k2

    开始时我想对k1 k2进行各种运算组合,但都无法保证k1 k2的运算组合是独一无二的。

    最后我决定用 ostringstream k1 k2 两个数字之间加上一个逗号,把他们变为字符串string,再利用map进行标记,相当成功

     

     

    最后我简单说说各种操作的数学表达式:

    1瓶的容量为v1,残余水量为k1 2瓶的容量为v2,残余水量为 k2

    那么 fill(1) 相当于 k1=v1  fill(2)相当于k2=v2  drop(1)相当于k1=0   drop(2)相当于k2=0

    对于Pour(1,2),若k1+k2<=v2, k2=k1+k2 k1=0  (有先后顺序)

                   否则k1=k1+k2-v2  k2=v2  (有先后顺序)

    Pour(2,1)亦同理

     

      1 //Memory Time
    2 //232K 32MS
    3
    4 #include<iostream>
    5 #include<string>
    6 #include<sstream>
    7 #include<map>
    8 using namespace std;
    9
    10 int v1,v2; //两个瓶子的容量
    11 int c; //目标残余水量
    12
    13 int k1,k2; //在某状态时两个瓶子的剩余水量,temporary
    14
    15 typedef class
    16 {
    17 public:
    18 int x,y; //当前状态(两个瓶子中的水量)
    19 int pos; //记录前一状态在队列queue中的下标
    20 int step; //当前步数
    21 }process;
    22
    23 //把整数a、b整合为 "a,b" 的字符串形式(不包括引号),用于标记状态
    24 string combAB(int a,int b)
    25 {
    26 string s;
    27 ostringstream oss;
    28
    29 oss<<a;
    30 oss<<',';
    31 oss<<b;
    32
    33 s=oss.str();
    34 oss.str(""); //清空oss对象内所存储的流
    35
    36 return s;
    37 }
    38
    39 void fill(int i)
    40 {
    41 switch(i)
    42 {
    43 case 1: {k1=v1; return;}
    44 case 2: {k2=v2; return;}
    45 }
    46 }
    47
    48 void drop(int i)
    49 {
    50 switch(i)
    51 {
    52 case 1: {k1=0; return;}
    53 case 2: {k2=0; return;}
    54 }
    55 }
    56
    57 void pour(int i,int j)
    58 {
    59 switch(i)
    60 {
    61 case 1: // v1 to v2
    62 {
    63 if(k1+k2<=v2)
    64 {
    65 k2=k1+k2;
    66 k1=0;
    67 }
    68 else
    69 {
    70 k1=k1+k2-v2;
    71 k2=v2;
    72 }
    73 return;
    74 }
    75 case 2: // v2 to v1
    76 {
    77 if(k1+k2<=v1)
    78 {
    79 k1=k1+k2;
    80 k2=0;
    81 }
    82 else
    83 {
    84 k2=k1+k2-v1;
    85 k1=v1;
    86 }
    87 return;
    88 }
    89 }
    90 }
    91
    92 void BFS(void)
    93 {
    94 int operation[1000]={0}; //当前步的操作: 1z0:清空z瓶子 2z0:装满z瓶子 3xy:从x瓶倒向y瓶
    95
    96 map<string,bool>vist;
    97 vist["0,0"]=true;
    98
    99 process queue[1000]; //状态队列
    100 int head,tail;
    101 queue[head=0].x=0;
    102 queue[tail=0].y=0;
    103 queue[tail++].step=0;
    104
    105 string ts; //temporary
    106 while(head<tail)
    107 {
    108 process p=queue[head];
    109
    110 if(p.x==c || p.y==c) //得到要求的剩余水量c
    111 {
    112 cout<<p.step<<endl;
    113
    114 /*下标回溯,输出操作过程*/
    115
    116 int ps=p.step;
    117 int* steps=new int[ps+1]; //从1到p.step顺序记录各步操作的下标,不使用steps[0]
    118
    119 steps[ps--]=tail-1;
    120 while(ps)
    121 {
    122 steps[ps]=queue[ steps[ps+1] ].pos;
    123 ps--;
    124 }
    125
    126 for(int i=1;i<=p.step;i++)
    127 {
    128 int temp=operation[ steps[i]-1 ]; //注意各个数组间的下标关系
    129
    130 switch(temp/100)
    131 {
    132 case 1:
    133 {
    134 cout<<"DROP("<<(temp/10)%10<<')'<<endl;
    135 break;
    136 }
    137 case 2:
    138 {
    139 cout<<"FILL("<<(temp/10)%10<<')'<<endl;
    140 break;
    141 }
    142 case 3:
    143 {
    144 cout<<"POUR("<<(temp/10)%10<<','<<temp%10<<')'<<endl;
    145 break;
    146 }
    147 }
    148 }
    149
    150 delete steps;
    151
    152 return;
    153 }
    154
    155 /*装满v1*/
    156
    157 k1=p.x;
    158 k2=p.y;
    159 fill(1);
    160 ts=combAB(k1,k2);
    161 if(!vist[ts])
    162 {
    163 vist[ts]=true;
    164 queue[tail].x=k1;
    165 queue[tail].y=k2;
    166 queue[tail].step=p.step+1; //当前的操作步数
    167 queue[tail].pos=head; //前一步操作在queue[]中的下标
    168 operation[tail++]=210; //当前的操作
    169 }
    170
    171 /*装满v2*/
    172
    173 k1=p.x;
    174 k2=p.y;
    175 fill(2);
    176 ts=combAB(k1,k2);
    177 if(!vist[ts])
    178 {
    179 vist[ts]=true;
    180 queue[tail].x=k1;
    181 queue[tail].y=k2;
    182 queue[tail].step=p.step+1;
    183 queue[tail].pos=head;
    184 operation[tail++]=220;
    185 }
    186
    187 /*清空v1*/
    188
    189 k1=p.x;
    190 k2=p.y;
    191 drop(1);
    192 ts=combAB(k1,k2);
    193 if(!vist[ts])
    194 {
    195 vist[ts]=true;
    196 queue[tail].x=k1;
    197 queue[tail].y=k2;
    198 queue[tail].step=p.step+1;
    199 queue[tail].pos=head;
    200 operation[tail++]=110;
    201 }
    202
    203 /*清空v2*/
    204
    205 k1=p.x;
    206 k2=p.y;
    207 drop(2);
    208 ts=combAB(k1,k2);
    209 if(!vist[ts])
    210 {
    211 vist[ts]=true;
    212 queue[tail].x=k1;
    213 queue[tail].y=k2;
    214 queue[tail].step=p.step+1;
    215 queue[tail].pos=head;
    216 operation[tail++]=120;
    217 }
    218
    219 /*v1倒向v2*/
    220
    221 k1=p.x;
    222 k2=p.y;
    223 pour(1,2);
    224 ts=combAB(k1,k2);
    225 if(!vist[ts])
    226 {
    227 vist[ts]=true;
    228 queue[tail].x=k1;
    229 queue[tail].y=k2;
    230 queue[tail].step=p.step+1;
    231 queue[tail].pos=head;
    232 operation[tail++]=312;
    233 }
    234
    235 /*v2倒向v1*/
    236
    237 k1=p.x;
    238 k2=p.y;
    239 pour(2,1);
    240 ts=combAB(k1,k2);
    241 if(!vist[ts])
    242 {
    243 vist[ts]=true;
    244 queue[tail].x=k1;
    245 queue[tail].y=k2;
    246 queue[tail].step=p.step+1;
    247 queue[tail].pos=head;
    248 operation[tail++]=321;
    249 }
    250
    251 head++;
    252 }
    253
    254 cout<<"impossible"<<endl;
    255 return;
    256 }
    257
    258 int main(void)
    259 {
    260 while(cin>>v1>>v2>>c)
    261 BFS();
    262 return 0;
    263 }
  • 相关阅读:
    移动应用调试之Inspect远程调试
    使用Stickers拓展集成iMessage简单功能
    iOS 在工程内部创建一个静态库target
    Xcode10 library not found for -lstdc++ 找不到问题
    git 操作规范
    java里面jre版本过低怎么修改
    java实现滑动列表找到目标并且选择
    java实现获取toast弱提示
    查询语句集合
    java-clienk 实现获取手机应用设备信息
  • 原文地址:https://www.cnblogs.com/lyy289065406/p/2122527.html
Copyright © 2011-2022 走看看