非常可樂 HDU - 1495 (BFS + 模擬倒水過程 OR 數論)

傳送門

非常可樂

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

 

題解:這一題難點兒的都在不好想,尤其是搜索時候的模擬過程(即相互倒水的過程),想會這點兒基本上就能做了,但是有一點,標記數組vis別開大,不然就 TE , 我開的是vis[109][109][109] TE 了,換成vis[105][105][105]過了,雖然卡着時間過去的

先來看一下搜索的代碼:

#include<iostream>
#include<cstdio>
#include<algorithm>
#include<queue>
#include<cstring>
using namespace std;
int s[3] , vis[105][105][105];

struct cup{
  int c[3] , step;
}now;

int bfs(){
  queue<cup> q ;
  now.c[0] = s[0] ,now.c[1] = 0 , now.c[2] = 0 , now.step = 0;
  vis[now.c[0]][now.c[1]][now.c[2]] = 1;
  q.push(now);
  while(!q.empty()){
    now = q.front();
    if((now.c[0] == now.c[1] && now.c[2] == 0) || (now.c[0] == now.c[2] && now.c[1] == 0) || (now.c[1] == now.c[2] && now.c[0] == 0))
    //判斷終止條件,即有一個杯子是空,另外兩個杯子一樣多
    {
      return now.step;
    }
    q.pop();
    for(int i = 0 ; i < 3 ; i ++){
      //模擬倒水的 6 種情況 a 倒 b,c  ||  b倒 a , c   || c 倒 a , b
        for(int j = 0 ; j < 3 ; j ++){
        if(i != j){ // 非自己倒給自己的過程,即其他的倒水過程
          int k = s[j] - now.c[j];
          if(k > now.c[i]){
            k = now.c[i];
          }
          cup next = now;
          //第 i 杯往第 j 杯裏倒水過程
          next.c[i] = now.c[i] - k;
          next.c[j] = now.c[j] + k;
          next.step = now.step + 1;
          if(vis[next.c[0]][next.c[1]][next.c[2]] == 0){
            vis[next.c[0]][next.c[1]][next.c[2]] = 1;
            q.push(next);
          }
        }
      }
    }
  }
  return -1;
}

int main(){
  while(cin >> s[0] >> s[1] >> s[2] && s[0] + s[1] + s[2]){
    memset(vis,0,sizeof(vis));
    if(s[0] != s[1] + s[2]){
      printf("NO\n");
      break;
    }
    else{
      int ans = bfs();
      if(ans == -1)
        printf("NO\n");
      else
        printf("%d\n",ans);
    }
  }
  return 0 ;
}

 

還有一種數論的做法,可以參考一下https://blog.csdn.net/V5ZSQ/article/details/52097459這位大佬的講解很詳細,望對你們有幫助,

附上數論代碼;

#include<iostream>
#include<cstdio>
#include<algorithm>
using namespace std;
int main(){
  int a , b , c;
  while(cin >> a >> b >> c && (a + b + c)){
    a /= __gcd(b,c);
    if(a & 1)
      cout<<"NO\n";
    else
      cout<< a-1 <<endl;
  }
  return 0 ;
}

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章