非常可乐 (HDU - 1495)

题面

大家一定觉的运动以后喝可乐是一件很惬意的事情,但是seeyou却不这么认为。因为每次当seeyou买了可乐以后,阿牛就要求和seeyou一起分享这一瓶可乐,而且一定要喝的和seeyou一样多。但seeyou的手中只有两个杯子,它们的容量分别是N 毫升和M 毫升 可乐的体积为S (S<101)毫升 (正好装满一瓶) ,它们三个之间可以相互倒可乐 (都是没有刻度的,且 S==N+M,101>S>0,N>0,M>0) 。聪明的ACMER你们说他们能平分吗?如果能请输出倒可乐的最少的次数,如果不能输出"NO"。

输入

三个整数 : S 可乐的体积 , N 和 M是两个杯子的容量,以"0 0 0"结束。

输出

如果能平分的话请输出最少要倒的次数,否则输出"NO"。

样例输入

17 4 3
24 1 3
30 0 0

样例输出

1NO
23

提示

思路

倒水问题,当S为奇数时无解。数论有简便解法

代码

  1using namespace std;
  2
  3#define out(a) (cout<<__LINE__<<" : "#a" = "<<(a)<<endl)
  4typedef long long ll;
  5const int inf = 0x3f3f3f3f;
  6const int N = 1e2+5;
  7
  8bool vis[N][N][N] = {{{0}}};
  9int s, n, m, ans = 0;
 10
 11struct P {
 12    int n, m, s;
 13    int step;
 14};
 15
 16bool bfs() {
 17    memset(vis, 0, sizeof(vis));
 18
 19    P sp;
 20    sp.s = s;
 21    sp.n = 0;
 22    sp.m = 0;
 23    sp.step = 0;
 24
 25    queue<P> q;
 26    q.push(sp);
 27    vis[sp.s][sp.n][sp.m] = 1;
 28
 29    while(!q.empty()) {
 30        P tp = q.front();
 31        q.pop();
 32
 33        if((!tp.n&&tp.m==tp.s) || (!tp.m&&tp.n==tp.s) || (!tp.s&&tp.n==tp.m)) {
 34            ans = tp.step;
 35            return true;
 36        }
 37        P np = tp;
 38        int t;
 39
 40        if(tp.n) {
 41            t = tp.n+tp.m;
 42            if(t>m) {
 43                np.m = m;
 44            } else {
 45                np.m = t;
 46            }
 47            np.n = t-np.m;
 48            np.s = tp.s;
 49
 50            if(!vis[np.s][np.n][np.m]) {
 51                np.step = tp.step+1;
 52                q.push(np);
 53                vis[np.s][np.n][np.m] = 1;
 54            }
 55
 56            t = tp.n+tp.s;
 57            if(t>s) {
 58                np.s = s;
 59            } else {
 60                np.s = t;
 61            }
 62            np.n = t-np.s;
 63            np.m = tp.m;
 64
 65            if(!vis[np.s][np.n][np.m]) {
 66                np.step = tp.step+1;
 67                q.push(np);
 68                vis[np.s][np.n][np.m] = 1;
 69            }
 70        }
 71
 72        if(tp.m) {
 73            t = tp.m+tp.n;
 74            if(t>n) {
 75                np.n = n;
 76            } else {
 77                np.n = t;
 78            }
 79            np.m = t-np.n;
 80            np.s = tp.s;
 81
 82            if(!vis[np.s][np.n][np.m]) {
 83                np.step = tp.step+1;
 84                q.push(np);
 85                vis[np.s][np.n][np.m] = 1;
 86            }
 87
 88            t = tp.m+tp.s;
 89            if(t>s) {
 90                np.s = s;
 91            } else {
 92                np.s = t;
 93            }
 94            np.m = t-np.s;
 95            np.n = tp.n;
 96
 97            if(!vis[np.s][np.n][np.m]) {
 98                np.step = tp.step+1;
 99                q.push(np);
100                vis[np.s][np.n][np.m] = 1;
101            }
102        }
103
104        if(tp.s) {
105            t = tp.s+tp.n;
106            if(t>n) {
107                np.n = n;
108            } else {
109                np.n = t;
110            }
111            np.s = t-np.n;
112            np.m = tp.m;
113
114            if(!vis[np.s][np.n][np.m]) {
115                np.step = tp.step+1;
116                q.push(np);
117                vis[np.s][np.n][np.m] = 1;
118            }
119
120            t = tp.s+tp.m;
121            if(t>m) {
122                np.m = m;
123            } else {
124                np.m = t;
125            }
126            np.s = t-np.m;
127            np.n = tp.n;
128
129            if(!vis[np.s][np.n][np.m]) {
130                np.step = tp.step+1;
131                q.push(np);
132                vis[np.s][np.n][np.m] = 1;
133            }
134        }
135    }
136    return false;
137}
138
139int main(void) {
140    while(scanf("%d%d%d", &s, &n, &m)==3 && s && n && m) {
141        if(s%2==0 && bfs()) {
142            printf("%d\n", ans);
143        } else {
144            printf("NO\n");
145        }
146    }
147    return 0;
148}