1. 程式人生 > >HDU 1495 非常可樂 BFS/數論

HDU 1495 非常可樂 BFS/數論

[0 pac sca 此刻 gin 兩個 妹子 inpu urn

M - 非常可樂HDU - 1495

大家一定覺的運動以後喝可樂是一件很愜意的事情,但是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

拉著小妹子一起刷題……莫名debug了好久orz,推薦數論的解法哇,被代碼長度還有復雜度深深吸引啊有木有!雖然我不會orz……
emmmmm一開始有些蒙蔽,覺得是個數學題,然貳,大佬說,一眼就是BFS……嘛~記筆記:最少步數求解——BFS!
下面先碼BFS的解法(唔,感覺有點像是漢諾塔???漢諾塔也迷迷的orz)
先考慮一下有解的情況:這裏假設v[3]為三個杯子此刻裝有的可樂(假設v[0]>v[1]),那麽當v[0]==v[2]&&v[1]==0時,可樂被平分。
if(v[0]==v[2]&&v[0]==0) printf("%d\n",t);
無解情況就……隊列空了都沒找到滿足有解的狀態(這裏隊列實現)
每次以三個杯子裏的一個杯子為主,拿起來就往其他兩個杯子裏倒就好了,也沒有其他地方可以倒了233333
需要註意的是,這裏一直都是把v[i]的倒入v[j],處理的時候註意倒的量不要超過杯子的容量;
#include<iostream>
#include<stdio.h>
#include<queue>
#include<string.h>
using namespace std;
struct node
{
    int v[3];
    int t;
};
int a, b, c;
int cup[3];
bool vis[105][105];
void bfs()
{
    node d,e;
    queue<node>q;
    d.t = 0;
    d.v[0] = 0; d.v[1] = 0; d.v[2] = c;
    q.push(d);
    vis[
0][0] = 1; while (!q.empty()) { d = q.front(); q.pop(); if (d.v[0] == d.v[2] && d.v[1] == 0) { printf("%d\n", d.t); return; } for(int i=0;i<3;i++) for (int j = 0; j < 3; j++) { if (d.v[i]==0||d.v[j] == c||i==j) continue; //因為一直都是把i倒到j裏,i不為空,j不為滿,自己不能倒給自己 int l = min(cup[j], d.v[i] + d.v[j]) - d.v[j]; memcpy(&e, &d, sizeof(d)); e.v[i] -= l; e.v[j] += l; if (!vis[e.v[0]][e.v[1]]) { vis[e.v[0]][e.v[1]] = 1; e.t ++; q.push(e); } } } puts("NO"); } int main() { while (scanf("%d%d%d", &c, &a, &b)!=EOF) { if (a==0 || b==0 || c==0) break; memset(vis, 0, sizeof(vis)); cup[0] = max(a, b); cup[1] = min(a, b); cup[2] = c; bfs(); } return 0; }

數論 ……待續


HDU 1495 非常可樂 BFS/數論