您现在的位置: 中国男护士网 >> 考试频道 >> 计算机等级 >> 二级辅导 >> C十十 >> 辅导 >> 正文    
  C++程序设计例解(06) 【注册男护士专用博客】          

C++程序设计例解(06)

www.nanhushi.com     佚名   不详 

06.设有大小不等的X,Y,Z三个无刻度的油桶,分别能够盛满油X,Y,Z(例如,X=80,Y=50,Z=30),并约定X>Y>Z。初始时,仅X油桶盛满油,Y和Z油桶为空。要求程序寻找一种最少的分油步聚,在某个油桶中分出T升油(例如T=40)。
解:
令三个油桶的盛油情况为倒油过程的状态,则倒油过程就是状态变化的过程。为了记录倒油过程,程序引入倒油状态队列,将倒油过程中产生的状态存储在队列中。队列的每个元素记录每次分油后各个油桶的分油后各个油桶的盛油量和倒油轨迹等有关信息。程序反复从队列中取出第一个还未检查过的状态,对该状态下的每个油桶判断其是否可以倒出油,及是否可以倒进油。由于油桶没有刻度,分油时只能将某个油桶倒满或倒空。程序分别按倒空或倒满两种可能的倒油动作执行不同的处理,产生新的倒油状态,为避免某个倒油状态在队列中重复出现,程序只将未曾出现过的新状态及其倒油轨迹信息存入队列中,假定程序检查了相当多的状态后,或能找到解,或能确定问题无解。

倒油程序算法如下:
算法---无刻度油桶分油
{
输入各桶容量和目标容量;
将初始状态存入倒油状态队列;
设置其它初始值;
do
{
对状态队列中第一个还未检查的元素
在还未检查完每个倒出的桶且还未找到解且还未确定无解情况下循环
if(倒出桶有油)
在还未检查完每个桶且还未找到解且还未确定无解情况下循环
if(当前桶不是倒出桶且桶还有空)
{
确定本次倒油量;
在队列中检查倒油后的结果状态是否在队列中出现;
if(结果状态不在队列中出现)
{
将结果状态和轨迹信息存入队列;
if(有桶中的油达到目标容量)
设置找到解标志;
}
}
if(还未找到解)
{
修正队列第一个还未检查过的元素指针;
if(队列中的元素都已检查过)
设置无解标志;
}
}while(还未找到解且还未确定无解);
if(找到解)
{
根据倒油步聚的轨迹信息,形成倒油步聚序列;
输出倒油步聚序列;
}
}
倒油队列中的元素应包含下列信息:各桶的盛油量,该状态是从哪一个桶(源桶)倒向哪一个桶(目标桶)而形成的,形成该状态的元素在队列中的位置。根据以上算法编写如下程序。



程序代码如下:
#include<stdio.h>
#define N 100
#define BUCKETS 3
struct ele{
int state[BUCKETS]; /*各桶盛油量*/
int sbucket; /*源桶*/
int obucket; /*目标桶*/
int last; /*轨迹元素在队列中的下标*/
}q[N]; /*队列*/
int full[BUCKETS];
int i,j,k,found,unable,wi,wj,v,targ;
int head,tail;
void main()
{
/*输入各桶容量和目标容量*/
printf("Enter volume of buckets.\n");
for(i=0;i<BUCKETS;i++)
scanf("%d",&full[i]);
/*如要检查full[0]>full[1]>full[2],相应代码在此*/
printf("Enter volume of targ.\n");
scanf("%d",&targ); /*检查targ<=full[0]的代码在此*/
/*设置将初始状态存入倒油状态队列等初值*/
q[0].state[0]=full[0];
for(i=1;i<BUCKETS;i++)
q[0].state[i]=0;
q[0].sbucket=0;
q[0].obucket=0;
q[0].last=0;
found=unable=0;
head=tail=0;
do
{
/*对状态队列中第一个还未检查过的元素在还未检查完每个倒出的桶
且还未找到解且还未确定无解情况下循环*/
for(i=0;i<BUCKETS&&!found&&!unable;i++)
if(q[head].state[i]>0) /*倒出桶有油*/
/*在还未检查完每个油桶且还未找到解且还未确定无解情况下循环*/
for(j=0;j<BUCKETS&&!found&&!unable;j++)
if(j!=i&&q[head].state[j]<full[j])
{ /*当前桶不是倒出桶且桶还有空*/
/*确定本次倒油量*/
if(q[head].state[i]>full[j]-q[head].state[j])
v=full[j]-q[head].state[j];
else v=q[head].state[i];
wi=q[head].state[i]-v;
wj=q[head].state[j]+v;
/*在队列中检查倒油后的结果状态是否在队列中出现*/
for(k=0;k<=tail;k++)
if(q[k].state[i]==wi&&q[k].state[j]==wj) break;
if(k>tail) /*结果状态不在队列中出现*/
{
/*将结果状态和轨迹信息存入队列*/
tail++;
q[tail].state[i]=wi;
q[tail].state[j]=wj;
q[tail].state[3-i-j]=q[head].state[3-i-j];
q[tail].sbucket=i+1;
q[tail].obucket=j+1;
q[tail].last=head;
/*如有桶达到目标盛油量,则设置找到解标志*/
if(wi==targ||wj==targ)found=1;
}
}
if(!found) /*还未找到解*/
{
head++; /*修正队列第一个还未检查过元素指针*/
if(head>tail) /*队列中的元素都已检查过*/
unable=1; /*设置无解标志*/
}
}while(!found&&!unable); /*还未找到解且还未确定无解*/
if(found) /*找到解*/
{
/*根据倒油步聚的轨迹信息,形成倒油步聚序列*/
i=tail;
j=-1;
do /*原倒油步聚逆向链接,现改为正向链接*/
{
k=q[i].last;
q[i].last=j;
j=i;
i=k;
}while(j);
/*输出倒油步聚序列*/
for(k=q[k].last;k>=0;k=q[k].last)
{
printf("%5d to %2d:",q[k].sbucket,q[k].obucket);
for(i=0;i<BUCKETS;i++)
printf("%4d",q[k].state[i]);
printf("\n");
}
}
else printf("Unable!\n");
}

程序运行结果如下:


 

文章录入:杜斌    责任编辑:杜斌 
  • 上一篇文章:

  • 下一篇文章:
  • 【字体: 】【发表评论】【加入收藏】【告诉好友】【打印此文】【关闭窗口
     

    联 系 信 息
    QQ:88236621
    电话:15853773350
    E-Mail:malenurse@163.com
    免费发布招聘信息
    做中国最专业男护士门户网站
    最 新 热 门
    最 新 推 荐
    相 关 文 章
    没有相关文章
    专 题 栏 目

      网友评论:(只显示最新10条。评论内容只代表网友观点,与本站立场无关!)                            【进男护士社区逛逛】
    姓 名:
    * 游客填写  ·注册用户 ·忘记密码
    主 页:

    评 分:
    1分 2分 3分 4分 5分
    评论内容:
  • 请遵守《互联网电子公告服务管理规定》及中华人民共和国其他各项有关法律法规。
  • 严禁发表危害国家安全、损害国家利益、破坏民族团结、破坏国家宗教政策、破坏社会稳定、侮辱、诽谤、教唆、淫秽等内容的评论 。
  • 用户需对自己在使用本站服务过程中的行为承担法律责任(直接或间接导致的)。
  • 本站管理员有权保留或删除评论内容。
  • 评论内容只代表网友个人观点,与本网站立场无关。