例7-3倒水问题(一般隐式图遍历)

版权声明:本文为博主原创文章,转载请声明原创网址。 https://blog.csdn.net/lagoon_lala/article/details/81291124

题目:

题目疑似有误:示例中“一种方法是……(4,2,1)”可能是(4,2,0)

思路:

系统状态(v0,v1,v2)作为结点,有向图

用结构体存状态和fa指针

MAX=1000

输入abc,x,

倒水操作,把所有结果放入队列

防止成环,vis[][][]

 

扫描二维码关注公众号,回复: 3577922 查看本文章

倒水操作:轮流取两杯子,倒入倒出操作(判断剩余容量)

(创建状态结点u,复制原有状态保存ij杯子改变后的值)

杯子i倒入j

杯子i有水,j没满

则倒入 杯子i中的水量与j的剩余容量 中的较小值

处理fa、vis

(剩余容量需要用到最大容量,保存成全局数组比较方便)

 

V1 v2 v3

V1=0,v2=1

01 0,2 1,2

倒水有2*3个方向,两个杯子值用Tempv[2]只能传递一个方向,6个方向用数组存太麻烦,直接临时用值遍历

在哪里新建结点

知识点:

赋值运算返回值是:赋的值

代码:

//6 3 1 4
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#define MAX 1000
typedef struct Node{
	int v[3];
	struct Node *fa;
}node;
bool vis[MAX][MAX][MAX];
int a[3];
void vlu(node* n,int a,int b,int c){ 
	n->v[0]=a;
	n->v[1]=b;
	n->v[2]=c;
}
node* newnode(){
	node* n=(node*)malloc(sizeof(node));
	vlu(n,0,0,0);
	n->fa=NULL;
	return n;
}

node* pour(int i,int j,node* n){
	if(n->v[i]&&(a[j]-n->v[j])){
		node* u=newnode();
		memcpy(u,n,sizeof(*n));
		int changev=u->v[i]<=(a[j]-u->v[j])?u->v[i]:(a[j]-u->v[j]);
		u->v[i]-=changev;
		u->v[j]+=changev;
		u->fa=n;
		return u;
	}else return NULL;
}
node* bfs(int a,int b,int c,int x){
	node* q[MAX];
	node* temp,*u;
	int front=0,rear=0;
	node* n=newnode();
	vlu(n,a,0,0);
	vis[a][0][0]=1;
	q[rear++]=n;
	while(front<rear){
		temp=q[front++];
		if(temp->v[0]==x||temp->v[1]==x||temp->v[2]==x)return temp;
		for(int i=0;i<3;i++){
			for(int j=0;j<3;j++){
				if(i!=j){
					//pour中cpy temp建u 
					if((u=pour(i,j,temp))!=NULL&&!vis[u->v[0]][u->v[1]][u->v[2]]){q[rear++]=u;//检查是否需要保留上一个临时变量
						vis[u->v[0]][u->v[1]][u->v[2]]=1;
					}
//					fa在pour中处理了 
				}
			}
		}
	}
	return NULL;
}
void print_ans(node* n) {//需要从前往后可以再加一个栈保存ans 
	printf("(%d,%d,%d)",n->v[0],n->v[1],n->v[2]);
	if(n->fa!=NULL){
		printf("<-");
		print_ans(n->fa);
	}
}
int main(){
	int x;
	node *temp;
	scanf("%d%d%d%d",&a[0],&a[1],&a[2],&x);
	temp=bfs(a[0],a[1],a[2],x);
	print_ans(temp);
	return 0;
}

猜你喜欢

转载自blog.csdn.net/lagoon_lala/article/details/81291124