NYOJ 三個水杯

2022-06-16 17:15:15 字數 4049 閱讀 2585

題目**:

這道題做了三天,內心是痛苦的。幾次想到放棄,但是又不忍心現有的成果,又不想借鑑別人的**。我相信我可以。就堅持下來了。最後也通過了。做這道題的感想就是流淚並快樂著。或許這也就是acmer的樂趣吧。

這道題收穫是巨大的。過後看網上說就是佇列 + 搜尋。我感覺則不然。我認為他是搜尋 + 半個動態規劃。為什麼這麼說呢?

1.佇列的作用在這兒就是達到遞迴的效果。然而我就用遞迴的方式實現它,這點可以忽略。概括之,就是搜尋的應用。

2.開始的時候,我只是單純的遞迴去做,結果對,但是超時了(後面有超時的**)。這裡就需要用到動規的知識了。即把每乙個已求得的狀態到終態的距離儲存下,以後會大量用到,這樣就不用接著遞迴下去了。省了很多時間。

具體思路是這樣的:

總共就6種情況:a->b  a->c  b->a  b->c  c->a  c->b。用遞迴搜尋的經典形式:邊界條件 + for迴圈。

不斷地對當前狀態到終態的距離進行更新。當存在乙個更小的距離時,就更新。最後的state[a][0][0]就是最後結果。需要注意的是:**的第31行,要保證將要出現的狀態沒有在遞迴的過程中(從初態到現在這乙個分支)出現過,不然就會陷入死迴圈。程式的146行也是個關鍵點:當遞迴返回時,上層狀態到終態的距離需要下一層的加1 ,牽強的說成這是狀態轉移方程吧(至少有相似之處,細細品味)。is_exist陣列記錄的是:從初態到當前狀態的這個分支中是否出現過。

超時**:這種情況沒有進行狀態儲存

1 #include 2 typedef struct

state;

5 state remember[1000];6

inttop;

7int

capacity_a,capacity_b,capacity_c;

8int

e1,e2,e3;

9int

cnt;

1011

int judge(int a,int b,int

c)16}17

return1;

18}1920

void dfs(int a,int b,int

c)27

28state cur;

2930

for(int i = 0; i < 6; i++)else

40if(judge(a-t, b+t, c))

4546}47

break;48

case

1:///

a->c

49if(a != 0 && capacity_c - c != 0)else

55if(judge(a - t,b,c + t))60}

61break;62

case

2:///

b->a

63if(b != 0 && capacity_a - a != 0)else

69if(judge(a+t,b-t,c))74}

75break;76

case

3:///

b->c

77if(b != 0 && capacity_c - c != 0)else

83if(judge(a, b-t, c+t))88}

89break;90

case

4:///

c->a

91if(c != 0 && capacity_a - a != 0)else

97if(judge(a+t, b, c-t))

102}

103break

;104

case

5:///

c->b

105if(c != 0 && capacity_b - b != 0)else

111if(judge(a, b+t, c-t))

116}

117break

;118

}119

}120 top--;

121}

122123

intmain()

138return0;

139 }

accept**:

1 #include 2

intcapacity_a,capacity_b,capacity_c;

3int

e1,e2,e3;

4int

cnt;

5int state[100][100][100];///

記錄狀態到終態的記錄,預設為inf

6int is_exist[100][100][100];///

記錄是否是遞迴過後的狀態78

int dfs(int a,int b,int

c)14

15for(int i = 0; i < 6; i++)else

25if(state[a-t][b+t][c] < 60000)30

}31if(is_exist[a-t][b+t][c] == 0)

3637}38

break;39

case

1:///

a->c

40if(a != 0 && capacity_c - c != 0)else

46if (state[a-t][b][c+t] < 60000)51

}52if(is_exist[a-t][b][c+t] == 0)

5758}59

break;60

case

2:///

b->a

61if(b != 0 && capacity_a - a != 0)else

67if(state[a+t][b-t][c] < 60000)72

}73if(is_exist[a+t][b-t][c] == 0)

7879}80

break;81

case

3:///

b->c

82if(b != 0 && capacity_c - c != 0)else

88if(state[a][b-t][c+t] < 60000)93

}94if(is_exist[a][b-t][c+t] == 0)99

100}

101break

;102

case

4:///

c->a

103if(c != 0 && capacity_a - a != 0)else

109if(state[a+t][b][c-t] < 60000

)114

}115

if(is_exist[a+t][b][c-t] == 0

)120

121}

122break

;123

case

5:///

c->b

124if(c != 0 && capacity_b - b != 0)else

130if(state[a][b+t][c-t] < 60000

)135

}136

if(is_exist[a][b+t][c-t] == 0

)141

142}

143break

;144

}145

}146

return

state[a][b][c];

147}

148149

intmain()

161162 state[capacity_a][0][0] = 61000; is_exist[capacity_a][0][0] = 1

;163 dfs(capacity_a,0,0

);164

if(state[capacity_a][0][0] >= 60000

)165 printf("

-1\n");

166else

167 printf("

%d\n

",state[capacity_a][0][0

]);168

}169

return0;

170 }

NYOJ 三個水杯

時間限制 1000 ms 記憶體限制 65535 kb 難度 4 描述給出三個水杯,大小不一,並且只有最大的水杯的水是裝滿的,其餘兩個為空杯子。三個水杯之間相互倒水,並且水杯沒有標識,只能根據給出的水杯體積來計算。現在要求你寫出乙個程式,使其輸出使初始狀態到達目標狀態的最少次數。輸入第一行乙個整數n...

NYOJ 搜尋 三個水杯

這道題是個廣度搜尋,借用佇列實現的。對搜尋還是處於入門的階段,所以也是看了別人的分析才能寫出來 所以貼出來與大家共勉 參考文章 首先,是畫了一張圖如下所示 步驟分析 比如從第一列測試資料出發 6,3,1和4,1,1 第 一 讓6,0,0先進來,然後對其進行倒水開始。此時只有第乙個被子有水 0不等於0...

nyoj 三個水杯 BFS

解題思路 有三種容量的杯子 v1,v2,v3 記錄每乙個杯子裡水的體積為 s1,s2,s3 每乙個杯子的剩餘容量為水杯裡的水在相互傾倒的時候會有以下的兩種情況 1 乙個杯子a所剩的容量 大小為va sa 比水杯b要倒過來的水 大小為sb 大的時候可以將b裡的水全部倒到a中,最終a中水的體積為sa s...