HDU1495非常可樂

2021-10-04 05:37:41 字數 4890 閱讀 1151

題目鏈結

problem description

大家一定覺的運動以後喝可樂是一件很愜意的事情,但是seeyou卻不這麼認為。因為每次當seeyou買了可樂以後,阿牛就要求和seeyou一起分享這一瓶可樂,而且一定要喝的和seeyou一樣多。但seeyou的手中只有兩個杯子,它們的容量分別是n 毫公升和m 毫公升 可樂的體積為s (s<101)毫公升 (正好裝滿一瓶) ,它們三個之間可以相互倒可樂 (都是沒有刻度的,且 s==n+m,101>s>0,n>0,m>0) 。聰明的acmer你們說他們能平分嗎?如果能請輸出倒可樂的最少的次數,如果不能輸出"no"。

input

三個整數 : s 可樂的體積 , n 和 m是兩個杯子的容量,以"0 0 0"結束。

output

如果能平分的話請輸出最少要倒的次數,否則輸出"no"。

sample input

7 4 3

4 1 3

0 0 0

sample output

no

3

樣例的輸出結果解析:

設s是瓶子(我看做大杯子),a、b兩個杯子

s=4a=1

b=3400

1031

1220

2所以三次的騰挪,可以讓s中的可樂平分

雖然知道這個是bfs題,但是僅僅對dfs有一點了解的情況下,實在是不清楚怎麼做的,既然是廣度搜尋,那如何記錄深度呢?要知道dfs可是用引數記錄的

經過學長講解,可以用佇列的先進先出的性質結合結構體來做dfs

第一步,根據題意建立結構體和jud陣列:

typedef

struct

h;

剛聽完自己做的時候只定義了s、a、b。。。最精髓的t沒有定義,導致走了不少彎路

我們可以把三個杯子每種可能的容量叫做狀態,就是說,最開始的狀態就是

瓶子容量等於s,兩個小杯子為0,我們需要按照資料規模開個鄉音的bool陣列防止兩個杯子之間反覆倒來倒去的存在(其實不一定是兩個杯子倒來倒去,有可能有其他組合也能組成永動不停的情況,舉個最簡單的例子利於以後的自己理解。)

**理解:

//操作

if(操作後形成的狀態以前沒有)

第二步:規定邊界,這題邊界很好想:就是存在兩個杯子的容量相同
//操作前:s代表總量,當前s代表的是當前大杯子容納的

if((當前s==當前a )&& 當前s==s/

2||當前b==當前a && 當前b==s/

2||當前s==當前b && 當前s==s/2)

//停止廣搜

第三步:思考什麼規定成全域性變數:

很顯然,三個杯子的總容量和可樂總量比較適合作為全域性變數(因為狀態合不合理需要靠這三個量評判,不能出現乙個杯子裝不下的情況出現,這段話作為下面的剪枝環節的鋪墊)

第四步:把初始狀態裝入佇列頭中去

這一步可以當做bfs的初始化來做。

然後就是考慮bfs的思考規律

dfs就是遞迴到底,直到沒法遞迴才返回上一層,而bfs需要把一層的每個點都走一遍,一開始真的搞不懂該怎麼做,stl的理解還是太淺既然用了佇列+結構體成員表示層數,就不在需要用遞迴的引數去表示層數了

那麼。。bfs的引數到底代表啥?

int

main()

bfs(s,a,b)

;//把邊界傳進去

while

(!q.

empty()

) jud =

false

;//全域性的jud,是否找到邊界狀態的標誌,總不能引數帶乙個jud把,顯得bfs的定義太臃腫了

memset

(jud,0,

sizeof

(jud));

//清零

}}

dfs是遞迴,bfs是迴圈

bfs的注意點:

1、佇列定義成全域性的!

2、用初狀態初始化佇列!

、#include

#include

#include

using

namespace std;

typedef

long

long ll;

bool jud[

101]

[101][

101]

;inline ll read()

inline

void

out(ll a)

typedef

struct

h;h h1, h2;

//乙個是存起始狀態的,乙個是動態的

int time;

bool jud;

queueq;

//佇列

void

bfs(

int s,

int a,

int b)

//s->a

if(h1.s)

else

h2.b = h1.b;if(

!jud[h2.s]

[h2.a]

[h2.b])}

//s->b,上面的複製過來,a變成b,b變成a就行了

if(h1.s)

else

h2.a = h1.a;if(

!jud[h2.s]

[h2.a]

[h2.b])}

//a->b

//a->s

//b->a

//b->s}if

(jud)

else

cout <<

"no"

<< endl;

}int

main()

bfs(s,a,b)

;while

(!q.

empty()

) jud =

false

;//全域性的jud,是否找到邊界狀態的標誌,總不能引數帶乙個jud把,顯得bfs的定義太臃腫了

memset

(jud,0,

sizeof

(jud));

//清零

}}

通過本題總結一些bfs的特點:

1、用引數做邊界

2、用while代替遞迴,這也是它跟dfs的乙個區別

3、bfs大致可分解成

思路有點亂,等待後續完善

#include

#include

#include

using

namespace std;

typedef

long

long ll;

bool jud[

101]

[101][

101]

;inline ll read()

inline

void

out(ll a)

typedef

struct

h;h h1, h2;

//乙個是存起始狀態的,乙個是動態的

int time;

bool jud;

queueq;

//佇列

void

bfs(

int s,

int a,

int b)

//s->a

if(h1.s)

else

h2.b = h1.b;if(

!jud[h2.s]

[h2.a]

[h2.b])}

//s->b,上面的複製過來,a變成b,b變成a就行了

if(h1.s)

else

h2.a = h1.a;if(

!jud[h2.s]

[h2.a]

[h2.b])}

//a->b

if(h1.a)

else

h2.s = h1.s;if(

!jud[h2.s]

[h2.a]

[h2.b])}

//a->s

if(h1.a)

else

h2.b = h1.b;if(

!jud[h2.s]

[h2.a]

[h2.b])}

//b->a

if(h1.b)

else

h2.s = h1.s;if(

!jud[h2.s]

[h2.a]

[h2.b])}

//b->s

if(h1.b)

else

h2.a = h1.a;if(

!jud[h2.s]

[h2.a]

[h2.b])}

}if(jud)

else

cout <<

"no"

<< endl;

}int

main()

bfs(s,a,b)

;while

(!q.

empty()

) jud =

false

;//全域性的jud,是否找到邊界狀態的標誌,總不能引數帶乙個jud把,顯得bfs的定義太臃腫了

memset

(jud,0,

sizeof

(jud));

//清零

}}

hdu 1495 非常可樂

題意 給你三個容器讓你平分可樂,求最少的步數。思路 一看到求最少步數,就想到了廣搜,但是沒有思路,但看別人分情況,瞬間就明白啦。可以s n,s m,n s,n m,m s,m n這六種情況討論就行,每種又有倒完和倒不完兩種情況,直到出現兩個容器都有s 2,這就是最少步數。但s是奇數時是不能平分的,三...

hdu 1495 非常可樂

hdu 1495 非常可樂 題目大意 給你三個容器,他們的容量分別是 s,n,m 且s n m,給你s,n,m。s代表裝在容器裡可樂,n和m代表的是兩個杯子的容量,求他們能否平分這杯可樂。如果能就輸出倒的最小次數,如果不能就輸出 no。題目分析 也就是要達到能 s 2,0,s 2或 0 s 2,s ...

hdu 1495 非常可樂

兩個杯子按大小排序,為s m n,1.只要n滿了,就把n裡的東西放到s中 2.只要m非空,就把m中的放到n中 3.如果m為空,把s中的放到m中 超時 include int n,m,s int main if ss aa bb 0 得到均分 if bb b 若小杯子裡裝滿可樂,將小杯子裡的可樂倒入可...