POJ 3414 Pots 我没有用广搜做

来源:互联网 发布:北京行知实验小学咋样 编辑:程序博客网 时间:2024/06/07 11:17

Pots

Time Limit : 2000/1000ms (Java/Other)   Memory Limit : 131072/65536K (Java/Other)
Total Submission(s) : 25   Accepted Submission(s) : 11
Special Judge
Problem Description

You are given two pots, having the volume of A and B liters respectively. The following operations can be performed:

  1. FILL(i)        fill the pot i (1 ≤ i ≤ 2) from the tap;
  2. DROP(i)      empty the pot i to the drain;
  3. POUR(i,j)    pour from pot i to pot j; after this operation either the potj is full (and there may be some water left in the pot i), or the poti is empty (and all its contents have been moved to the pot j).

Write a program to find the shortest possible sequence of these operations that will yield exactlyC liters of water in one of the pots.

 

Input
On the first and only line are the numbers A, B, and C. These are all integers in the range from 1 to 100 and C≤max(A,B).
 

Output
The first line of the output must contain the length of the sequence of operations K. The following K lines must each describe one operation. If there are several sequences of minimal length, output any one of them. If the desired result can’t be achieved, the first and only line of the file must contain the word ‘impossible’.
 

Sample Input
3 5 4
 

Sample Output
6FILL(2)POUR(2,1)DROP(1)POUR(2,1)FILL(2)POUR(2,1)
 
    这是一道广搜题,可是如果用广搜我觉得会非常麻烦,不好考虑而且代码冗长。 
    仔细考虑问题可以发现倒水的倒法只有两种,
                 1). 水->n;n->m;m->0;        //如此往复;
                 2). 水->m;m->n;n->0;           //如此往复;
    我们只要找出两种倒法哪一种可以先得出我们所需要的解,即最优解即可,数据也不是很大,两个暴力枚举也是可以的。
    但是我们还要思考什么样子的数字是没有解,如果没有解两个循环会被关了,及其尴尬。
    仔细思考,通过数学知识我们可以发现输入的C不是N,M的最大公因数的整数倍的时候会无解。

   下面是AC代码,我要早点打完回去看TI了,我再重申一次,LGD是不可战胜的。

#include <cstdio>#include <iostream>#include <string>using namespace std;int ans1[5000],ans2[5000];string ss[7]={"\0","FILL(1)","FILL(2)","POUR(1,2)","POUR(2,1)","DROP(1)","DROP(2)" };   //最后输出用的int gcd(int n,int m){                                                                   //大家熟悉的辗转相除法    if(m<=n){        return m==0?n:gcd(m,n%m);    }else{        return gcd(m,n);    }}int main(){    int n,m,c;    while(~scanf("%d%d%d",&n,&m,&c))                                                    //输入    {        int r1=0,r2=0,sw=0,fw=0;                                                        //sw,fw分别代表两个杯子里剩下的水,r1,r2是记录步数用的        if(c%gcd(n,m)!=0){printf("impossible\n");continue;}        while(sw!=c&&fw!=c)        {            if(!sw)            {                sw=m;                ans1[r1++]=2;            }            else if(fw==n)            {                fw=0;                ans1[r1++]=5;            }            else            {                ans1[r1++]=4;                fw+=sw;                                                                  //先把水全部倒进一个瓶子里                sw=0;                                                                    //因为水倒掉了,所以归零                if(fw>=n){sw=fw-n;fw=n;}                                                 //把多出来的水倒回去            }        }        sw=0,fw=0;        while(sw!=c&&fw!=c)        {            if(!fw)            {                fw=n;                ans2[r2++]=1;            }            else if(sw==m)            {                sw=0;                ans2[r2++]=6;            }            else            {                ans2[r2++]=3;                                                               //和上面同理                sw+=fw;                fw=0;                if(sw>=m){fw=sw-m;sw=m;}            }        }            if(r1>r2)                                                                       //输出函数            {                cout<<r2<<endl;                for(int i=0;i<r2;i++)                cout<<ss[ans2[i]]<<endl;            }            else            {                cout<<r1<<endl;                for(int i=0;i<r1;i++)                cout<<ss[ans1[i]]<<endl;            }    }    return 0;}