SPOJ上POUR1的建议?

时间:2013-07-25 21:56:06

标签: c++ algorithm graph-algorithm

我需要帮助解决这个问题POUR1。我认为 它可以用强力方法解决,但我读到这是一个图形问题(BFS)。我解决了ABCPATH,LABYR1,PT07Y,PT07Z,BITMAP等问题 但我不知道如何以BFS方式接近POUR1。

有人可以给我一些建议吗?

问题陈述:

考虑到两艘船,其中一艘可以容纳一升水,另一艘可容纳一升水,确定在其中一艘船中获得精确c升水所需的步数。

一开始两艘船都是空的。以下操作计为“步骤”:

  • 清空一艘船,
  • 填充船只,
  • 将水从一个容器倒入另一个容器,不会溢出,直到其中一个容器满或空。

输入:

整数t,1< = t< = 100,表示测试用例的数量,后跟t组输入数据,每组由三个正整数a,b,c组成,不大于40000,在单独的行中给出

输出:

对于每组输入数据,输出获得c升所需的最小步数,如果不可能则输出-1。

示例:

示例输入:

2
5
2
3
2
3
4

示例输出:

2
-1

2 个答案:

答案 0 :(得分:15)

这个问题有一个更简单的解决方案。不需要BFS。特设会做得很好。 方法1 - 填充A,将其清空为B.每当A变空时填充它,每当B变满时将其填满。 (所有上述行为都算作个别动作)。继续这个过程,直到你到达任何一个容器中所需的水量。获取此处的移动数量。 (说C1) 方法2 - 填充B,将其清空为A.每当B变空时将其填充回来,每当A变满时将其填满。继续这样,直到达到所需的金额。得到移动的数量C2) 答案是min(C1,C2) C ++中的源代码:

#include < cstdio > 
#include < algorithm >
using namespace std;

int pour(int A, int B, int C) {
  int move = 1, a = A, b = 0, tfr;
  while (a != C && b != C) {
    tfr = min(a, B - b);
    b += tfr;
    a -= tfr;
    move++;
    if (a == C || b == C)
      break;
    if (a == 0) {
      a = A;
      move++;
    }
    if (b == B) {
      b = 0;
      move++;
    }
  }
  return move;
}
/** Reason for calculating GCD of a,b is to check whether an integral solution of 
 *  equation of form ax + by = c exist or not, to dig deeper read Diophantine Equations
 */
int gcd(int a, int b) {
  if (b == 0)
    return a;
  return gcd(b, a % b);
}
int main() {
  int t, a, b, c;
  scanf("%d", & t);
  while (t--) {
    scanf("%d%d%d", & a, & b, & c);
    if (c > a && c > b)
      printf("-1\n");
    else if (c % gcd(a, b) != 0)
      printf("-1\n");
    else if (c == a || c == b)
      printf("1\n");
    else
      printf("%d\n", min(pour(a, b, c), pour(b, a, c)));
  }
  return 0;
}

答案 1 :(得分:5)

考虑所有先验可能状态的集合(例如[3,7]意味着Vessel1包含3个窝,而容器2包含7个窝)。您有一个有向图,其顶点是那些状态,其边是可能的移动。问题是在图中找到一个路径,将状态[0,0]连接到类型[c,?]的状态或类型[?,c]的状态。这种路径通常由BFS搜索。