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

Python019

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

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

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

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

#include<stdio.h>

#include<malloc.h>

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>0?getName(p1_goAd):"",p1_goAd>0?"下船":"")

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

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

        printf("%s%s",p2_take>0?getName(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>0?getName(take):"无货物",f==0?"p1":"p2",goAd!=0?getName(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==0?1: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=0i<counti++)

        pn=pn*10

    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 <stdio.h>

#include <stdlib.h>

#include <string.h>

#define MAX_STEP 20

//index: 0 - 狼,1-羊,2-草,3-人,value:0-本岸,1-对岸

int a[MAX_STEP][4]

int b[MAX_STEP]

char *name[] =

{

"空手",

"带狼",

"带羊",

"带草"

}

void search(int iStep)

{

int i

if (a[iStep][0] + a[iStep][1] + a[iStep][2] + a[iStep][3] == 4)

{

for (i = 0i <iStepi++)

{

if (a[i][3] == 0)

{

printf("%s到对岸\n", name[b[i] + 1])

}

else

{

printf("%s回本岸\n", name[b[i] + 1])

}

}

printf("\n")

return

}

for (i = 0i <iStepi++)

{

if (memcmp(a[i], a[iStep], sizeof(a[i])) == 0)

{

return

}

}

if (a[iStep][1] != a[iStep][3] &&(a[iStep][2] == a[iStep][1] || a[iStep][0] == a[iStep][1]))

{

return

}

for (i = -1i <= 2i++)

{

b[iStep] = i

memcpy(a[iStep + 1], a[iStep], sizeof(a[iStep + 1]))

a[iStep + 1][3] = 1 - a[iStep + 1][3]

if (i == -1)

{

search(iStep + 1)

}

else if (a[iStep][i] == a[iStep][3])

{

a[iStep + 1][i] = a[iStep + 1][3]

search(iStep + 1)

}

}

}

int main()

{

search(0)

return 0

}

#include <stdio.h>

#include <stdlib.h>

#include <string.h>

#define MAX_STEP 20

//index: 0 - 狼,1-羊,2-菜,3-农夫,value:0-本岸,1-对岸

int a[MAX_STEP][4]

int b[MAX_STEP]

char *name[] =

{

"空手",

"带狼",

"带羊",

"带菜"

}

void search(int iStep)

{

int i

if (a[iStep][0] + a[iStep][1] + a[iStep][2] + a[iStep][3] == 4)

{

for (i = 0i <iStepi++)

{

if (a[i][3] == 0)

{

printf("%s到对岸\n", name[b[i] + 1])

}

else

{

printf("%s回本岸\n", name[b[i] + 1])

}

}

printf("\n")

return

}

for (i = 0i <iStepi++)

{

if (memcmp(a[i], a[iStep], sizeof(a[i])) == 0)

{

return

}

}

if (a[iStep][1] != a[iStep][3] &&(a[iStep][2] == a[iStep][1] || a[iStep][0] == a[iStep][1]))

{

return

}

for (i = -1i <= 2i++)

{

b[iStep] = i

memcpy(a[iStep + 1], a[iStep], sizeof(a[iStep + 1]))

a[iStep + 1][3] = 1 - a[iStep + 1][3]

if (i == -1)

{

search(iStep + 1)

}

else if (a[iStep][i] == a[iStep][3])

{

a[iStep + 1][i] = a[iStep + 1][3]

search(iStep + 1)

}

}

}

int main()

{

search(0)

return 0

}