1. 程式人生 > >POJ-3414-兩個杯子倒水問題(寬搜+回溯)

POJ-3414-兩個杯子倒水問題(寬搜+回溯)

Northeastern Europe 2002, Western Subregion

題意:
給出兩個容積分別為 a 和 b 的pot,按照以下三種操作方式,求出能否在一定步數後,使者兩個pot的其中一個的水量為c。
      1.FILL(i):將ipot倒滿水。
      2.DROP(i):將ipot倒空水。
      3.POUR(i,j): 將ipot的水倒到jpot上,直至要麼ipot為空,要麼jpot為滿。
思路:
BFS求最短路徑步數,並在過程中利用回溯記錄路徑。

貼上程式碼:(要是你有足夠的耐心,這個程式碼還是容易理解的)

#include<queue>
#include<stdio.h>
#include<string.h>
#include<algorithm>
using namespace std;

struct P
{
    int x;
    int y;           //x,y用來記錄杯子中水的狀態
    int sx;
    int sy;          //sx,sy記錄路徑
    int v;           //用1,2,3,4,5,6,代表倒水的操作
    int vis;         //標記
    int num;         //記錄倒水操作的步驟數
}cup[110][110];

int a,b,c;
int flag;
int xx,yy;
int xxx,yyy;
int path[10000];
int bfs()
{
    queue<P>q;
    q.push(cup[0][0]);
    cup[0][0].vis=1;
    while(q.size())
    {
        P p=q.front();
        xx=p.x;
        yy=p.y;
        q.pop();
        if(xx==c || yy==c)
        {
            flag=1;
            break;
        }
        if(p.x>=0&&p.x<=a&&p.y>=0&&p.y<=b)
        {
            if(cup[a][p.y].vis==0)     //杯子a加滿
            {
                cup[a][p.y].sx=p.x;
                cup[a][p.y].sy=p.y;
                cup[a][p.y].vis=1;
                cup[a][p.y].num=cup[p.x][p.y].num+1;
                cup[a][p.y].v=1;
                q.push(cup[a][p.y]);
            }
            if(cup[0][p.y].vis==0)   //杯子a倒空
            {
                cup[0][p.y].sx=p.x;
                cup[0][p.y].sy=p.y;
                cup[0][p.y].vis=1;
                cup[0][p.y].num=cup[p.x][p.y].num+1;
                cup[0][p.y].v=2;
                q.push(cup[0][p.y]);
            }
            if(cup[p.x][b].vis==0)  //杯子b加滿
            {
                cup[p.x][b].sx=p.x;
                cup[p.x][b].sy=p.y;
                cup[p.x][b].vis=1;
                cup[p.x][b].num=cup[p.x][p.y].num+1;
                cup[p.x][b].v=3;
                q.push(cup[p.x][b]);
            }
            if(cup[p.x][0].vis==0)  //杯子b倒空
            {
                cup[p.x][0].sx=p.x;
                cup[p.x][0].sy=p.y;
                cup[p.x][0].vis=1;
                cup[p.x][0].num=cup[p.x][p.y].num+1;
                cup[p.x][0].v=4;
                q.push(cup[p.x][0]);
            }
            if(p.x+p.y-b>=0&&cup[p.x+p.y-b][b].vis==0)   //a倒入b,a有剩餘
            {
                cup[p.x+p.y-b][b].sx=p.x;
                cup[p.x+p.y-b][b].sy=p.y;
                cup[p.x+p.y-b][b].vis=1;
                cup[p.x+p.y-b][b].num=cup[p.x][p.y].num+1;
                cup[p.x+p.y-b][b].v=5;
                q.push(cup[p.x+p.y-b][b]);
            }
            if(p.x+p.y-b<0&&cup[0][p.x+p.y].vis==0)     //a倒入b,a空
            {
                cup[0][p.x+p.y].sx=p.x;
                cup[0][p.x+p.y].sy=p.y;
                cup[0][p.x+p.y].vis=1;
                cup[0][p.x+p.y].num=cup[p.x][p.y].num+1;
                cup[0][p.x+p.y].v=5;
                q.push(cup[0][p.x+p.y]);
            }
            if(p.x+p.y-a>=0&&cup[a][p.x+p.y-a].vis==0)  //b倒入a,b有剩餘
            {
                cup[a][p.x+p.y-a].sx=p.x;
                cup[a][p.x+p.y-a].sy=p.y;
                cup[a][p.x+p.y-a].vis=1;
                cup[a][p.x+p.y-a].num=cup[p.x][p.y].num+1;
                cup[a][p.x+p.y-a].v=6;
                q.push(cup[a][p.x+p.y-a]);
            }
            if(p.x+p.y-a<0&&cup[p.x+p.y][0].vis==0)    //b倒入a,b空
            {
                cup[p.x+p.y][0].sx=p.x;
                cup[p.x+p.y][0].sy=p.y;
                cup[p.x+p.y][0].vis=1;
                cup[p.x+p.y][0].num=cup[p.x][p.y].num+1;
                cup[p.x+p.y][0].v=6;
                q.push(cup[p.x+p.y][0]);
            }
        }
    }

    if(flag)
    {
        printf("%d\n",cup[xx][yy].num);
        int sum=cup[xx][yy].num;
        for(int i=sum;i>0;i--)
        {
            path[i]=cup[xx][yy].v;
            xxx=xx;
            yyy=yy;
            xx=cup[xxx][yyy].sx;
            yy=cup[xxx][yyy].sy;
        }
        for(int i=1;i<=sum;i++)
        {
           if(path[i]==1)      printf("FILL(1)\n");
           else if(path[i]==2) printf("DROP(1)\n");
           else if(path[i]==3) printf("FILL(2)\n");
           else if(path[i]==4) printf("DROP(2)\n");
           else if(path[i]==5) printf("POUR(1,2)\n");
           else if(path[i]==6) printf("POUR(2,1)\n");
        }
    }
    else
        printf("impossible\n");
}

int main()
{
    scanf("%d%d%d",&a,&b,&c);
    for(int i=0;i<110;i++)
    {
        for(int j=0;j<110;j++)
        {
            cup[i][j].x=i;
            cup[i][j].y=j;
            cup[i][j].sx=0;
            cup[i][j].sy=0;
            cup[i][j].v=0;
            cup[i][j].num=0;
            cup[i][j].vis=0;
        }
    }
    flag=0;
    memset(path,0,sizeof(path));
    bfs();
    return 0;
}



相關推薦

POJ-3414-杯子倒水問題+回溯

Northeastern Europe 2002, Western Subregion 題意: 給出兩個容積分別為 a 和 b 的pot,按照以下三種操作方式,求出能否在一定步數後,使者兩個pot的其中一個的水量為c。 1.FILL(i):將ipot倒滿水。 2.DROP(i):將ip

POJ-3414 Pots(杯子倒水問題) 【BFS】

題目傳送門 題目: 給你兩個杯子a,b,容量分別是A和B。可以執行以下操作: 1.FILL(i):將i倒滿水。 2.DROP(i):將i倒空水。 3.POUR(i,j): 將ipot的水倒到jpot上,直至要麼ipot為空,要麼jpot為滿。 求能否在一定步數的操作後,使得a,b

合併單鏈表連結串列方式

假設頭指標為La、Lb單鏈表分別為線性表LA、LB的儲存結構,現在要合併La、Lb得到單鏈表Lc void MergeList_L(LinkList La, LinkList Lb, LinkList Lc){ //已知La、Lb的元素按值非遞減排列 //歸併La、Lb得到單鏈表Lc,

用C程式設計,設定外部中斷INT0和INT1按鍵,優先順序IP=0x04,即把外部中斷1設定為高階優先順序,外部中斷0為低階優先順序,使外部中斷1巢狀在外部中斷0中。

問題 用C程式設計,設定兩個外部中斷(INT0和INT1)按鍵,優先順序IP=0x04,即把外部中斷1設定為高階優先順序,外部中斷0為低階優先順序,使外部中斷1巢狀在外部中斷0中。 要求:中斷觸發方式為下降沿觸發,按鍵有消抖功能 模擬 程式碼 #include <

【LeetCode】88. 合併有序陣列Merge Sorted Array

【 英文練習 | 中文練習 】 題目描述: 給定兩個有序陣列,合併它們,合併之後的陣列依舊有序。 解題思路: 從後向前存放。 public void merge(int[] nums1, int m, int[] nums2, int n) { if(nums

字串拼接不用strcat函式

字串拼接 要求不用strcat函式,具體思路如下: 先求出2個字串的長度 用迴圈將第二個字串的字元新增到第一個字串的後面 #include <iostream> #include <cstring> #define Max_

迷宮問題+回溯

    Time Limit: 1 Sec  Memory Limit:128 MB  64bit IO Format: %lld                                  [Submit][Status][Web Board] 設有一個N*N(

poj 3414 bfs 倒水,記錄路徑

題意:給你兩個壺,容量分別為a,b,初始都是0,再給你一個目標水量c,問經過幾次操作可以使得其中一個壺的水量為目標水量c,並且把操作步驟輸出。 6個操作: 1、FILL(1)//FILL(i),把 i 壺裝滿 2、FILL(2) 3、DROP(1)//DROP(i),把 i

最小割經典題點依附在一起的情況poj3469

minimum 兩個 color computer upd 情況 nim %d struct Dual Core CPU Time Limit: 15000MS Memory Limit: 131072K Total Submissions: 25099

P和P1指向了O和O1變量對象的地址, 而不是O和O1的內容(對象的實際地址)——充分證明@是取變量對象的地址,而不是變量裏面的內容,夠清楚!

com 告訴 cnblogs src logs es2017 strong bsp html 如圖,為什麽這樣取出來的p,p1的值不一樣呢? 165232328群友庾偉洪告訴我: P和P1指向了O和O1兩個變量(對象)的地址, 而不是O和O1的內容(對象

匯編語言——數據處理的基本問題處理的數據在什麽地方 要處理的數據有多長

inf ron 進行 end 尺寸 程序 訪問 com 尋址 bx、si、di、bp 1、在8086CPU 中,只有這4個寄存器(bx、bp、si、di)可以用在“[…]” 中來進行內存單元的尋址。 2、在“[…]” 中,這4個寄存器(bx、bp、si、di)可以單個出現,

java 識別字符串中字節數中文占字節,英文占一個

else if gpo pub div 字節 str length 英文 兩個 public static int byteNum(String str) { int m = 0; char arr[] =

ajax遇到的小bug

字符 過去 方案 ima 錯誤 復選框 兩個 中項 技術分享 1.公司的一個因子系數配置頁面,可以勾選中多個復選框進行刪除,刪除後保存操作軌跡表。但不知道之前是誰這樣寫的 此挖坑人,對於選中的多個復選框循環調用後臺方法,但是這些請求都請求後臺了,執行完畢的先後順序並沒有保

oracle sql 遊標的簡單用法tip:sql中單引號表示一個單引號

--遊標遍歷某個欄位 (打印出來) declare            res_sql varchar2(2000); cursor cur is            select f_

微策略2011校園招聘筆試題找出陣列中只出現一次的數字

分享一下我老師大神的人工智慧教程!零基礎,通俗易懂!http://blog.csdn.net/jiangjunshow 也歡迎大家轉載本篇文章。分享知識,造福人民,實現我們中華民族偉大復興!        

編寫一個Java應用程式,當用戶在輸入對話方塊中輸入日期後日期格式為YYYYMMDD,如1999年1月12日應輸入為19990112,程式將判斷日期的先後順序,以及日期之間的間隔天數

編寫一個Java應用程式,當用戶在輸入對話方塊中輸入兩個日期後(日期格式為YYYYMMDD, 如1999年1月12日應輸入為19990112), 程式將判斷兩個日期的先後順序, 以及兩個日期之間的間隔天數(例如1999年1月1日和1999年1月2日之間的間隔是1天。  

合併連結串列c++

合併兩個連結串列(c++) 輸入的連結串列按照其元素從小到大的順序排序,輸出的連結串列也按從小到大的順序排序,請合併兩個連結串列 template<typename E> Link<E> * LList<E>::mergeList(LList<

射線檢測模型,效果和程式碼一樣

坦克:public class TankeScript : MonoBehaviour { float hor, ver; //發射射線碰撞體檢測物件 RaycastHit hitInfo; //要移動到的目標點 Vector3 target; //坦克要旋轉的

PHP只保留字串首尾字元,隱藏中間用*代替字元時只顯示第一個

/** * 只保留字串首尾字元,隱藏中間用*代替(兩個字元時只顯示第一個) * @param [string] $user_name 字串 * @param [int] $head 左側保留位數 * @param [int] $foot 右側保留位數 * @r

我有500w單詞,你幫忙設計一個數據結構來進行儲存,存好之後,我有需求。程式人生程式碼copy

 1、來了一個新的單詞,需要判斷是否在這500w個單詞中 2、來了一個單詞字首,給出500w個單詞中有多少個單詞是該字首 package cango.scf.common.util; import java.util.HashMap; import java.util.