POJ-3414-兩個杯子倒水問題(寬搜+回溯)
題意:
給出兩個容積分別為 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.