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 }

 

posted @ 2012-05-17 16:40  BeatLJ  阅读(384)  评论(0编辑  收藏  举报