求狼羊白菜过河的C语言编程题详解。希望不要用数组解决。

求狼羊白菜过河的C语言编程题详解。希望不要用数组解决。,第1张

按照你的要求,不使用数组。

我的思路,起点货物狼、羊、白菜,人一直在开船,通过递归函数,每次靠岸尝试装卸货方案,直到找满足条件的方案。将可行方案存放在结构链表中形成 *** 作流水打印。

人狼羊菜存储方式模拟4位2进制,用1111表示,每位表示一个单位,1存在,0不存在。

#include<stdioh>

#include<malloch>

typedef enum{false,true}bool;

typedef struct opRecord//用结构链表记录 *** 作流水

{

    int p1_take;//p1载货值

    int p1_goAd;//p1卸货值

    int p2_take;//p2载货值

    int p2_goAd;//p2卸货值

    int cen;//递归层号

    struct opRecord next;

}OPR;

OPR oprHead;

OPR oprTail;

char getName(int b);//获取对应名称

int beEaten(int p1,int p2);//检查是否发生被吃事件,发生返回1,未发生返回0

int toShip(int p1,int p2,int ship,bool f);//递归函数:上船人及任意一组合,返回状态,1:方案可行;0:方案不可行

int getFist(int pn);//获取物品组合中第一个

void addLog(int p1_take,int p1_goAd,int p2_take,int p2_goAd,int cen);//将有效 *** 作添加进日志,cen相同,将视为修改覆盖

void printfLog();//打印 *** 作流水

OPR findLogBycen(int cen);//通过cen查找流水。 有返回节点指针。无返回NULL

int count=1;

int flag=0;//标识变量=1成立;  =0不成立

int cen=0;

int main()

{

    int p1=111,ship=1000,p2=0000;//p1,p2分别表示两岸,4位数每一位分别表示人狼羊菜,位数值1表示存在,0表示不存在

    oprHead=(OPR )malloc(sizeof(OPR));

    oprHead->next=NULL;

    oprTail=NULL;

    printf("河岸有人、狼、羊、白菜要过河,船每次载人及一物,为避免人上船后狼吃羊或羊吃菜\n开始生成方案:\n\n");

    if(toShip(&p1,&p2,&ship,0))

    {

        printf("\n开始生成结果报告:\n");

        printfLog();

    }

    else

        printf("无可行方案!!\n");

    return 0;

}

void addLog(int p1_take,int p1_goAd,int p2_take,int p2_goAd,int cen)//将有效 *** 作添加进日志,cen相同,将视为修改覆盖,

{

    OPR oprNew=findLogBycen(cen);

    if(oprNew==NULL)//通过查找。确认无记录,新增记录

    {

        oprNew=(OPR )malloc(sizeof(OPR));

        oprNew->p1_take=p1_take;

        oprNew->p1_goAd=p1_goAd;

        oprNew->p2_take=p2_take;

        oprNew->p2_goAd=p2_goAd;

        oprNew->cen=cen;

        oprNew->next=NULL;

        if(oprHead->next==NULL)

            oprHead->next=oprNew;

        else

            oprTail->next=oprNew;

        oprTail=oprNew;

    }

    else//查找发现已有记录,修改

    {

        oprNew->p1_take=p1_take;

        oprNew->p1_goAd=p1_goAd;

        oprNew->p2_take=p2_take;

        oprNew->p2_goAd=p2_goAd;

    }

}

OPR findLogBycen(int cen)//通过cen查找流水。 有返回节点指针。无返回NULL

{

    OPR headSave=oprHead;

    while(headSave->next!=NULL)

    {

        if(headSave->next->cen==cen)

            return headSave->next;

        headSave=headSave->next;

    }

    return NULL;

}

void printfLog()//打印 *** 作流水

{

    OPR headSave=oprHead;

    int p1_take,p1_goAd,p2_take,p2_goAd,cen,p1TOp2,p2TOp1;

    while(headSave->next!=NULL)

    {

        p1_take=headSave->next->p1_take;

        p1_goAd=headSave->next->p1_goAd;

        p2_take=headSave->next->p2_take;

        p2_goAd=headSave->next->p2_goAd;

        cen=headSave->next->cen;

        if(p1_take>0 || p1_goAd>0)

            p1TOp2=1;

        else

            p1TOp2=0;

        if(p2_take>0 || p2_goAd>0)

            p2TOp1=1;

        else

            p2TOp1=0;

        printf(" *** 作流水%2d:",cen);

        printf("%s%s",p1TOp2>0"从p1":"",p2TOp1>0"从p2":"");

        printf("%s%s",p1_goAd>0getName(p1_goAd):"",p1_goAd>0"下船":"");

        printf("%s%s",p1_take>0getName(p1_take):"",p1_take>0"上船":"");

        printf("%s%s",p2_goAd>0getName(p2_goAd):"",p2_goAd>0"下船":"");

        printf("%s%s",p2_take>0getName(p2_take):"",p2_take>0"上船":"");

        if(headSave->next->next!=NULL)

            printf("。之后行驶方向:%s%s\n",p1TOp2>0"p1->p2":"",p2TOp1>0"p1<-p2":"");

        else

            printf("\n");

        headSave=headSave->next;

    }

}

char getName(int b)//获取对应名称

{

    if(b==1000)

        return "人";

    else if(b==100)

        return "狼";

    else if(b==10)

        return "羊";

    else if(b==1)

        return "菜";

    return "";

}

int toShip(int p1,int p2,int ship,bool f)//递归函数:上船人及任意一组合;lastTake:上一次承载物体,首次调用传0;f=0:p1->p2方向;1:反向。返回状态,1:方案可行;0:方案不可行;

{

    int take=-1,goAd,gdflag=1,cenSave;//take:上船物体。  goAd:下船物体。gdflag:标识变量,p2判断能否直接下船,1能0不能

    cenSave=++cen;

    while(1)

    {

        goAd=ship-1000;

        if(f==0)//准备p1往p2

        {

            if(take==-1)

                take=getFist(p1);

            p1-=take;

            p1+=goAd;

            gdflag=1;//标识置1,等到p2首先尝试直接卸货

        }

        else//准备p2往p1

        {

            if(take==-1 && gdflag==0)

            {

                take=getFist(p2);

                printf("开始尝试替换货物:\n");

            }

            if(gdflag==1)//如果p2可以直接卸货

                p2+=goAd;

            else//如果不能直接卸货,尝试带走一个同时卸货

            {

                p2-=take;

                p2+=goAd;

            }

        }

        printf("递归层级%d:假设%s从%s上船。%s下船,%s方向行驶。\n",cenSave,take>0getName(take):"无货物",f==0"p1":"p2",goAd!=0getName(goAd):"无货物",f==0"p1往p2":"p2往p1");

        if(beEaten(p1,p2))//如果发生被吃,假设失败,还原数据,选择下一假设

        {

            if(f==0)

            {

                p1+=take;

                p1-=goAd;

            }

            else

            {

                if(gdflag==1)//p2点确定不能直接卸货,还原数据,标识置0

                {

                    printf("----不能直接卸货,货物%s回到船上。",getName(goAd));

                    p2-=goAd;

                    gdflag=0;

                    continue;

                }

                else//不能直接卸货并尝试替换货物失败,选择下一个货物替换

                {

                    p2+=take;

                    p2-=goAd;

                }

            }

            if(take==1)

            {

                printf("本次靠岸无可行的装卸方案,返回层级%d!\n",cenSave-1);

                return 0;

            }

            take=take/10;//尝试选择下一个货物

            continue;

        }

        else

        {

            if(f==1 && gdflag==1)//p2直接卸货假设成立船清空

                ship=1000;

            else

                ship=1000+take;//换货假设成立货物装船

            if(p1==0)//如果已经完全转移

            {

                printf("所有货物过河成功!!\n");

                return 1;

            }

            if(f==0)

                addLog(take,goAd,0,0,cenSave);//生成流水日志

            else

                addLog(0,0,take,goAd,cenSave);//生成流水日志

            if(toShip(p1,p2,ship,f==01:0))

            {

                return 1;

            }

            else//由于下级失败,本回合重新选择

            {

                gdflag=0;

                continue;

            }

        }

    }

}

int getFist(int pn)//获取物品组合中第一个

{

    int i,count=0;

    while(1)//上船物体从岸上第一个物体开始选择

    {

        if(pn<=1)

            break;

        pn=pn/10;

        count++;

    }

    for(i=0;i<count;i++)

        pn=pn10;

    return pn;

}

int beEaten(int p1,int p2)//检查是否发生被吃事件,发生返回1,未发生返回0

{

    int ren=0;

    if(p1==110 && ++ren==1)

        printf("----河岸p1狼把羊吃了!重新选择\n");

    if(p2==110 && ++ren==1)

        printf("----河岸p2狼把羊吃了!重新选择\n");

    if(p1==11 && ++ren==1)

        printf("----河岸p1羊把菜吃了!重新选择\n");

    if(p2==11 && ++ren==1)

        printf("----河岸p2羊把菜吃了!重新选择\n");

    return ren;

}

#include &lt;stdio.h&gt;#define MAX 100typedef enum BOOL{ FALSE = 0, TRUE = 1 }BOOL;typedef union Items{struct {char boy : 1;char girl : 1;char father : 1;char mother : 1;char police : 1;char thief : 1;char : 0;};char c;}*pItems, Items;struct{Items item[MAX];int boat[MAX];int length;}stack; int Boat[2];Items ItemMask[12];char* msg[4] = { &quot;comes back single.&quot; &quot;comes back together.&quot;, &quot;pasts the river single.&quot;, &quot;past the river together.&quot; };char* msgn[12] = { &quot;father&quot;, &quot;mother&quot;, &quot;police&quot;, &quot;thief&quot;, &quot;police and the thief&quot;, &quot;police and the father&quot;,&quot;police and the mother&quot;, &quot;police and the boy&quot;, &quot;police and the girl&quot;, &quot;father and the boy&quot;, &quot;mother and the girl&quot;, &quot;father and the mother&quot;};BOOL IsLegal ( Items item ){Items t1, t2, t3;Items t4, t5, t6;t1.c = 0, t2.c = 0, t3.c = 0;t4.c = 0, t5.c = 0, t6.c = 0;t1.girl = 1, t1.father = 1, t1.mother = 0;t4.girl = 1, t4.father = 1, t4.mother = 1;t2.boy = 1, t2.father = 0, t2.mother = 1;t5.boy = 1, t5.father = 1, t5.mother = 1;t3.thief = 1, t3.police = 0;t6.thief = 1, t6.police = 1;if (( t4.c &amp; item.c ) == t1.c ) {return FALSE; }if (( t5.c &amp; item.c ) == t2.c ) {return FALSE;}if ((( item.c &amp; t6.c ) == t3.c ) &amp;&amp; (( item.c ^ t3.c ) != 0)) {return FALSE;} return TRUE;}BOOL IsInStack ( Items item, int boat ){int i = 0;for ......余下全文>>

以上就是关于求狼羊白菜过河的C语言编程题详解。希望不要用数组解决。全部的内容,包括:求狼羊白菜过河的C语言编程题详解。希望不要用数组解决。、c程序,主仆过河问题。、等相关内容解答,如果想了解更多相关内容,可以关注我们,你们的支持是我们更新的动力!

欢迎分享,转载请注明来源:内存溢出

原文地址: https://outofmemory.cn/zz/10072230.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2023-05-04
下一篇 2023-05-04

发表评论

登录后才能评论

评论列表(0条)

保存