题意

大家一定觉的运动以后喝可乐是一件很惬意的事情,但是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
---------------------------------------------------------我是分割线----------------------------------------------------------------------------------------------------------------------
某童靴的一般思路  (感谢@陌类  提供的代码)

  (较麻烦的题解, 好像多数人都这么写~

 #include <stdio.h>
#include <string.h>
#include <algorithm>
#include <queue>
#define N 110
using namespace std;
int vis[N][N][N];
int s,n,m;
struct node
{
int n,s,m,step;
};
int cheak(int x,int y,int z)
{
if(x==&&y==z)
return ;
if(y==&&x==z)
return ;
if(z==&&x==y)
return ;
return ;
}
int bfs()
{
queue<node>Q;
node now,next;
now.s=s;
now.n=;
now.m=;
now.step=;
vis[s][][]=;
Q.push(now);
while(Q.size())
{
now=Q.front();
Q.pop();
if(cheak(now.s,now.n,now.m))//检查状态
{
return now.step;
}
for(int i=;i<=;i++)
{
if(now.s!=)
{
if(i==&&now.n!=n)
{
if(now.n+now.s>n)
{
next.n=n;
next.s=now.s-(n-now.n);
}
else
{
next.n=now.n+now.s;
next.s=;
}
next.m=now.m;
next.step=now.step+;
if(!vis[next.s][next.n][next.m])
{
vis[next.s][next.n][next.m]=;
Q.push(next);
}
}
else if(i==&&now.s!=&&now.m!=m)
{
if(now.m+now.s>m)
{
next.m=m;
next.s=now.s-(m-now.m);
}
else
{
next.m=now.m+now.s;
next.s=;
}
next.n=now.n;
next.step=now.step+;
if(!vis[next.s][next.n][next.m])
{
vis[next.s][next.n][next.m]=;
Q.push(next);
}
}
}
if(now.n!=)
{
if(i==&&now.m!=m)
{
if(now.m+now.n>m)
{
next.m=m;
next.n=now.n-(m-now.m);
}
else
{
next.m=now.m+now.n;
next.n=;
}
next.s=now.s;
next.step=now.step+;
if(!vis[next.s][next.n][next.m])
{
vis[next.s][next.n][next.m]=;
Q.push(next);
}
}
else if(i==&&now.n!=&&now.s!=s)
{
if(now.m+now.s>s)
{
next.s=s;
next.n=now.n-(s-now.s);
}
else
{
next.s=now.n+now.s;
next.n=;
}
next.m=now.m;
next.step=now.step+;
if(!vis[next.s][next.n][next.m])
{
vis[next.s][next.n][next.m]=;
Q.push(next);
}
}
}
if(now.m!=)
{
if(i==&&now.m!=&&now.n!=n)
{
if(now.n+now.m>n)
{
next.n=n;
next.m=now.m-(n-now.n);
}
else
{
next.n=now.n+now.m;
next.m=;
}
next.s=now.s;
next.step=now.step+;
if(!vis[next.s][next.n][next.m])
{
vis[next.s][next.n][next.m]=;
Q.push(next);
}
}
else if(i==&&now.m!=&&now.s!=s)
{
if(now.s+now.m>s)
{
next.s=s;
next.m=now.m-(s-now.s);
}
else
{
next.s=now.s+now.m;
next.m=;
}
next.n=now.n;
next.step=now.step+;
if(!vis[next.s][next.n][next.m])
{
vis[next.s][next.n][next.m]=;
Q.push(next);
}
} }
}
}
return -;
}
int main()
{
while(scanf("%d%d%d",&s,&n,&m),s+n+m!=)
{
if(s%!=)
{
printf("NO\n");
}
else
{
memset(vis,,sizeof(vis));
int ans;
ans=bfs();
if(ans>=)
printf("%d\n",ans);
else
printf("NO\n");
}
}
return ;
}

 

 简单点评

  在上面的代码, 每次for循环都将枚举六种情况 ,1->2 , 1-》3,2-》3 ,2-》1,3-》1,3-》2  ,并且每种情况又要分为两种来讨论......

   重复的部分太多了~

  重复的部分太多了~

  不够简洁,代码太长长了。

  出错误了一不好找啊!

-------------------------------------------------------------------------------------------------------------------------------------我是分割线---------------------------------------------------------------------------------------------------------------------------------------------------------------------------

  起先我也是这么做的,后来我想了一个相对简单的优化办法:

  进行结构体的嵌套 ,结构体cup 的 a[1]/a[2]/a[3]分别代表这 三个容器 ,其中结构体 cup中 up 代表一个容器的装水上限 ,now  代表现在的水量! 再用 结构体node 将cup和step 封装起来!

 #include<iostream>
#include<algorithm>
#include<cstdio>
#include<cstring> //by @山枫叶纷飞
#include<cstdlib>
#include<cmath>
#include<string>
#include<set>
#include<queue>
using namespace std;
typedef long long ll;
double dinf=99999999.9, mm=1e-;
const int N=,inf=0x3f3f3f3f;
int s,n,m;
int vis[N][N][N];
struct cup
{
int up,now;
};
struct node
{
cup a[]; ///进行结构体的嵌套 ,a[1]/a[2]/a[3] 分别表示三个容器
int step;
};
int bfs( )
{
int i,j,k;
queue<node>Q;
node p,q;
p.a[].now=s;p.a[].up=s;
p.a[].now=;p.a[].up=n;
p.a[].now=;p.a[].up=m;
p.step=;
memset(vis,,sizeof(vis));vis[s][][]=;
Q.push(p);
while(Q.size()>)
{
p=Q.front(); ///从队列中取到的现在的状态
Q.pop();
if((p.a[].now==s/&&p.a[].now==s/) || (p.a[].now==s/&&p.a[].now==s/))///判断是否达到预期结果
return p.step;
if((p.a[].now==s/&&p.a[].now==s/))///判断是否达到预期结果(太长了,拆成了两段)
return p.step; for(i=;i<=;i++)
{
for(j=;j<=;j++)
{
if(i==j || p.a[i].now==||p.a[j].now==p.a[j].up)///简易排除
continue; q=p;///初始化,q 代表由p 延伸来的下一状态 int dif=p.a[j].up-p.a[j].now;///表示容器a[j]最多可添加水量
if(p.a[i].now>=dif)///若容器a[j]可被填满水
{
q.a[i].now=p.a[i].now-dif;
q.a[j].now=p.a[j].up;
}
else ///若容器a[j]不能装满水
{
q.a[i].now=;
q.a[j].now=p.a[i].now+p.a[j].now;
}
q.step=p.step+;
if(vis[q.a[].now][q.a[].now][q.a[].now]==)
{
vis[q.a[].now][q.a[].now][q.a[].now]=;
Q.push(q);
}
}
} }
return -;
}
int main()
{
while(scanf("%d%d%d",&s,&n,&m),s+n+m)
{
if(s%!=)///奇数一定无法均分成两份
printf("NO\n");
else
{
int k=bfs();
if(k==-)
printf("NO\n");
else
printf("%d\n",k);
}
} return ;
}

 简单点评

  两重for 循环,用a[i] 和a[j] 来模拟全部六种情况的倒水过程 ,省了超过100行的代码, 结构体的含义一目了然,  就是结构体名字写起来太长了!

  还有要注意的是: { q=p;///初始化,q 代表由p 延伸来的下一状态}这段代码的位置很重要, 每次新的内层for循环都要记得将q重新初始化, 不然会造成意料之外的错误! 当时debug 到了 "debug人在天涯"!

---------------------------------------------------------我是分割线----------------------------------------------------------------------------------------------------------------------
其他思路
  这个题目用数论也是可以做的! 近似玄学,,,感兴趣的话自行百度!

HDU-1495 非常可乐 (嵌套结构体-广搜 对比 一般广搜)的更多相关文章

  1. HDU 1495 非常可乐 (只是转了个弯的广搜题)

    N - 非常可乐 =========================================================================================== ...

  2. abap中结构体嵌套结构体。

    1: 结构体中嵌套结构体. *&---------------------------------------------------------------------* *& Re ...

  3. C语言 结构体(嵌套结构体--结构体数组)

    //结构体--嵌套结构体和结构体数组 #define _CRT_SECURE_NO_WARNINGS #include <stdio.h> #include <stdlib.h> ...

  4. BFS(倒水问题) HDU 1495 非常可乐

    题目传送门 /* BFS:倒水问题,当C是奇数时无解.一共有六种情况,只要条件符合就入队,我在当该状态vised时写了continue 结果找了半天才发现bug,泪流满面....(网上找份好看的题解都 ...

  5. matlab学习笔记12_2创建结构体数组,访问标量结构体,访问非标量结构体数组的属性,访问嵌套结构体中的数据,访问非标量结构体数组中多个元素的字段

    一起来学matlab-matlab学习笔记12 12_2 结构体 创建结构体数组,访问标量结构体,访问非标量结构体数组的属性,访问嵌套结构体中的数据,访问非标量结构体数组中多个元素的字段 觉得有用的话 ...

  6. go变量、类的概念以及类的使用方式,嵌套结构体

    go变量.类的概念以及类的使用方式,嵌套结构体 Go变量 go使用var声明变量,当声明变量时,这个变量对应的值总是会被初始化.这个值要么用指定的值初始化,要么用零值(即变 量类型的默认值)做初始化. ...

  7. hdu 1495 非常可乐 (广搜)

    题目链接 Problem Description 大家一定觉的运动以后喝可乐是一件很惬意的事情,但是seeyou却不这么认为.因为每次当seeyou买了可乐以后,阿牛就要求和seeyou一起分享这一瓶 ...

  8. hdu 1495 非常可乐 广搜

    #include<iostream> #include<cstdio> #include<cstring> #include<queue> ][][]; ...

  9. HDU 1495 非常可乐(数论,BFS)

    非常可乐 Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others) Total Submi ...

随机推荐

  1. IE6不支持position:fixed的解决方法

    解决IE6不支持position:fixed的方法,非常简单,具体调用请参考下面: /*让position:fixed在IE6下可用! */ .fixed-top /* 头部固定 */{positio ...

  2. ecshop广告分析

    ecshop模板中,显示广告的库项目是ad_position.lbi,其内容只有一个语句: {insert name='ads' id=$ads_id num=$ads_num} smarty的ins ...

  3. 如何连接新浪sae共享数据库

    网上找了很久,太杂了,下文介绍如何连接新浪sae共享数据库,方便有效 1.首先贴出官方文档: 以下是一些和共享MySQL数据库服务相关的预定义常量,你可以直接引用这些参数来连接数据库: 用户名 : S ...

  4. CUDA零内存拷贝 疑问考证

    今天思考了一下CUDA零内存拷贝的问题,感觉在即将设计的程序中会派上用场,于是就查了一下相关信息. 以下是一些有帮助的链接: cuda中的零拷贝用法--针对二维指针 cuda中的零拷贝用法--针对一维 ...

  5. 处理浏览器兼容 各个浏览器的标识 hack

    Firefox 浏览器 @-moz-document url-prefix() { .selector { property: value; } } 支持所有Gecko内核的浏览器 (包括Firefo ...

  6. JavaScript从入门到忘记

    JavaScript是一门编程语言,浏览器内置了JavaScript语言的解释器,所以在浏览器上按照JavaScript语言的规则编写相应代码之,浏览器可以解释并做出相应的处理. 一.如何编写 二.变 ...

  7. 在ubuntu14.04上安装mono4.4 + jexus + mvc6

    0.准备工作 在/usr下建立一个文件夹,方便管理源码 cd /usr mkdir opensource cd opensource 安装vim(文本编辑器,不习惯用vim可以换成其他的) apt-g ...

  8. VB6之HTTP服务器的实现(二)

    接上篇,这次做了小小的改动和提升.增加了对POST的支持和对其他方法(GET和POST之外的)选择405回复.另外,增加了对CGI的支持,目前可以使用C语言来写(是不是好蠢的赶脚).相对于上篇,整体做 ...

  9. Java 标准DBUtil 写法

    package xueruan.com.util; import java.sql.Connection; import java.sql.DriverManager; import java.sql ...

  10. 关于WIN7 内存占用很大的 问题svchost.exe

    svchost.exe 是用来启动系统服务的,所以某个 svchost.exe 占用内存过大,可能就是它启动的那个服务占用内存过大,所以只要停止并禁用那个服务就行了. 一般来说占用内存最大的服务是 S ...