HDOJ搜索专题之非常可乐

题目模型:给定3个无刻度容器,容器的容积均为正整数,初始状态为第一个容器装满水,其它2个空着,问是否能将第一个容器中的水平分,若能输出最少操作步数,否则输出"NO".

分析:典型的状态空间搜索题,要求最少步数,可以用BFS,将3个容器中中的水量组合定义为状态,倒水操作会造成状态转移。目标状态为某两个容器中水量相等且总和为总水量。一个小的优化是当总水量为奇数时,直接输出"NO".

View Code
 1 #include <stdio.h>

 2 #include <string.h>

 3 #include <queue>

 4 #define N 101

 5 #define MIN(a,b) ((a)<(b)?(a):(b))

 6 using namespace std;

 7 typedef struct node

 8 {

 9   int v[3];

10   int t;

11 }node;

12 node cur,next;

13 queue<node> Q;

14 int c[3];

15 char vis[N][N];

16 bool is_ok(node tmp)

17 {

18   for(int i=0;i<3;i++)

19   {

20     for(int j=i+1;j<3;j++)

21     {

22       if(tmp.v[i]==tmp.v[j] && tmp.v[i]+tmp.v[j]==c[0]) return true;

23     }

24   }

25   return false;

26 }

27 node st_tran(node tmp,int i,int j)

28 {

29   int d=MIN(tmp.v[i],c[j]-tmp.v[j]);

30   if(d==0)  tmp.t=-1;

31   else

32   {

33     tmp.v[i]-=d;

34     tmp.v[j]+=d;

35     tmp.t++;

36   }

37   return tmp;

38 }

39 void bfs()

40 {

41   bool success=false;

42   int ans;

43   while(!Q.empty()) Q.pop();

44   memset(vis,0,sizeof(vis));

45   cur.v[0]=c[0];

46   cur.v[1]=0;

47   cur.v[2]=0;

48   cur.t=0;

49   vis[cur.v[0]][cur.v[1]]=1;

50   Q.push(cur);

51   while(!Q.empty() && !success)

52   {

53     cur=Q.front(),Q.pop();

54     if(is_ok(cur))  success=true,ans=cur.t;

55     for(int i=0;!success && i<3;i++)

56     {

57       for(int j=0;!success && j<3;j++)

58       {

59         if(i==j)  continue;

60         next=st_tran(cur,i,j);

61         if(next.t==-1 || vis[next.v[0]][next.v[1]])  continue;

62         if(is_ok(next)) success=true,ans=next.t;

63         else  vis[next.v[0]][next.v[1]]=1,Q.push(next);

64       }

65     }

66   }

67   if(success) printf("%d\n",ans);

68   else  puts("NO");

69 }

70 int main()

71 {

72   while(scanf("%d%d%d",&c[0],&c[1],&c[2])&&c[0])

73   {

74     if(c[0]%2)  puts("NO");

75     else  bfs();

76   }

77   return 0;

78 }

 

你可能感兴趣的:(搜索)