您的位置:首页 > 其它

HDOJ搜索专题之非常可乐

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

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

View Code

#include <stdio.h>
#include <string.h>
#include <queue>
#define N 101
#define MIN(a,b) ((a)<(b)?(a):(b))
using namespace std;
typedef struct node
{
int v[3];
int t;
}node;
node cur,next;
queue<node> Q;
int c[3];
char vis

;
bool is_ok(node tmp)
{
for(int i=0;i<3;i++)
{
for(int j=i+1;j<3;j++)
{
if(tmp.v[i]==tmp.v[j] && tmp.v[i]+tmp.v[j]==c[0]) return true;
}
}
return false;
}
node st_tran(node tmp,int i,int j)
{
int d=MIN(tmp.v[i],c[j]-tmp.v[j]);
if(d==0)  tmp.t=-1;
else
{
tmp.v[i]-=d;
tmp.v[j]+=d;
tmp.t++;
}
return tmp;
}
void bfs()
{
bool success=false;
int ans;
while(!Q.empty()) Q.pop();
memset(vis,0,sizeof(vis));
cur.v[0]=c[0];
cur.v[1]=0;
cur.v[2]=0;
cur.t=0;
vis[cur.v[0]][cur.v[1]]=1;
Q.push(cur);
while(!Q.empty() && !success)
{
cur=Q.front(),Q.pop();
if(is_ok(cur))  success=true,ans=cur.t;
for(int i=0;!success && i<3;i++)
{
for(int j=0;!success && j<3;j++)
{
if(i==j)  continue;
next=st_tran(cur,i,j);
if(next.t==-1 || vis[next.v[0]][next.v[1]])  continue;
if(is_ok(next)) success=true,ans=next.t;
else  vis[next.v[0]][next.v[1]]=1,Q.push(next);
}
}
}
if(success) printf("%d\n",ans);
else  puts("NO");
}
int main()
{
while(scanf("%d%d%d",&c[0],&c[1],&c[2])&&c[0])
{
if(c[0]%2)  puts("NO");
else  bfs();
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: