数据结构算法题2

数据结构算法题2

(分酒问题)已知有三个容量分别为3千克、5千克和8千克的并且是没有刻度的酒瓶,3千克和5千克的瓶子均装满了酒,而8千克的瓶子为空。现要求仅用这三个酒瓶将这些酒均分为两个4千克并分别装入5千克和8千克的瓶子中。

#include <stdio.h>
#include<stdbool.h>
#include<stdlib.h>

typedef struct State
{
	int a,b,c;
	struct State *prev;//用来找到正确方法后,打印倒酒路径
}State;

typedef struct Node//队列的节点结构
{
	State *state;
	struct Node *next;
}Node;

Node *create_Node(State *state)//创建队列结点
{
	Node *node=malloc(sizeof(Node));
	node->state=state;
	node->next=NULL;
	return node;
}

typedef struct Queue//队列结构
{
	Node *front;
	Node *rear;
}Queue;

Queue *create_queue(void)//创建队列
{
	Queue *queue=malloc(sizeof(Queue));
	queue->front=NULL;
	queue->rear=NULL;
	return queue;
}

bool isEmpty(Queue *queue)//队空
{
	return queue->front==NULL;	
}

//入队
void pushQueue(Queue *queue,State *state)
{
	Node *node=create_Node(state);
	if(isEmpty(queue))
	{
		queue->front=node;
		queue->rear=node;
	}
	else
	{
		queue->rear->next=node;
		queue->rear=node;
	}
}

//出队
State *popQueue(Queue *queue)
{
	if(isEmpty(queue))return NULL;
	Node *temp=queue->front;
	State *state=temp->state;
	queue->front=queue->front->next;
	if(queue->front==NULL)queue->rear=NULL;
	free(temp);
	return state;
}
void clearQueue(Queue *queue) {
    while (!isEmpty(queue)) {
        State *state = popQueue(queue);
        free(state);
    }
    free(queue);
}


//检查是否访问过
bool isVisited(State *state,bool visited[4][6][9])
{
	return visited[state->a][state->b][state->c];	
}

//标记状态为访问过
void Visited(State *state,bool visited[4][6][9])
{
	visited[state->a][state->b][state->c]=true;	
}

//打印状态
void printfState(State *state)
{
	if(state==NULL)return;
	printfState(state->prev);
	printf("(A: %d ,B: %d ,C: %d)\n",state->a,state->b,state->c);
}


//current当前状态   capacities为每个瓶子容量  from从哪个瓶子  to倒入哪个瓶子
void tryPour(Queue* queue, State *current, int from, int to, int capacities[3], bool visited[4][6][9])
{
	int bottles[3]={current->a,current->b,current->c};//初始化瓶子当前有多少酒
	int pourAmount=(bottles[from]<capacities[to]-bottles[to]) ? bottles[from] : capacities[to]-bottles[to];//计算可以倒多少酒
	bottles[from]-=pourAmount;
	bottles[to]+=pourAmount;

	//更新状态
	State *newstate=malloc(sizeof(State));
	newstate->a=bottles[0];
	newstate->b=bottles[1];
	newstate->c=bottles[2];
	newstate->prev=current;

	if(!isVisited(newstate,visited))//如果没有被访问过,就入队
	{
		pushQueue(queue,newstate);
		Visited(newstate,visited);//入队后,更新状态
	}
	else
	free(newstate);
}

void bfs(State *start,int capacities[3])//广度优先遍历
{
	bool visited[4][6][9]={false};
	Queue *queue=create_queue();
	pushQueue(queue,start);
	Visited(start,visited);//将初始状态标记为访问le
	while(!isEmpty(queue))
	{
		State *current=popQueue(queue);
		if(current->b==4&&current->c==4)
		{
			printfState(current);
            clearQueue(queue);
			return;
		}
		tryPour(queue,current,0,1,capacities,visited);
		tryPour(queue,current,0,2,capacities,visited);	
		tryPour(queue,current,1,0,capacities,visited);
		tryPour(queue,current,1,2,capacities,visited);
		tryPour(queue,current,2,0,capacities,visited);
		tryPour(queue,current,2,1,capacities,visited);
	}
	printf("没有找到方法!");
    clearQueue(queue);
}

int main(int argc,const char* argv[])
{
	int capacities[3]={3,5,8};
	State *start=malloc(sizeof(State));
	start->a=3;
	start->b=5;
	start->c=0;
	start->prev=NULL;
	bfs(start,capacities);
	free(start);
	return 0;
}

  • 3
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值