(复习次数:1——吃力AC)POJ - 3414 pots

http://poj.org/problem?id=3414
代码借鉴大佬的,还是结构清楚点好
递归和循环差不多,想的是终止项和继续项
bfs队列可开全局,在入队之前标记
这是回溯的方法,还有一个方法是开数组记录路径,相比之下这个不用想次数,但是要记得入队时复制next到存的数组里
结构决定功能,功能决定结构,尽量多几个结构以多几个功能,不要互相绕弯子,比如这里是原现状态,操作,计数器构成的结构,尽管现状态也是数组下标,但是好用就要有。
注意判断不是(&&),用(!||!)判断,等等注意已经注释

#include<stdio.h>
#include<string.h>
#include<queue>
#define N 105
using namespace std;
int a,b,c;

struct node{
	int a,b;
	int sa,sb;
	int tag;
	int step;
}lu[N][N]={0};//各状态节点 lu[a][b] 

int vis[N][N]={0};//是0否1能走 

queue<node>q;//要先 using namespace std;

//tag 0~5
char ch[6][11]={"FILL(1)","FILL(2)","DROP(1)","DROP(2)","POUR(1,2)","POUR(2,1)"};

void print(node &now)
{
	if(now.sa||now.sb){//注意细节,是不到头,头是0&&0,则要判断 有||有! 
		print(lu[now.sa][now.sb]);
	}
	printf("%s\n",ch[now.tag]);
}

void push(node nex,int tag){
	if(vis[nex.a][nex.b]==0){
		nex.tag=tag;
		vis[nex.a][nex.b]=1;
		lu[nex.a][nex.b]=nex;//细节决定成败,注意复制到数组内,不存起来,等下数组里是没有记录的 
		q.push(nex);
	}
}

void bfs()
{
	vis[0][0]=1;
	q.push(lu[0][0]);
	
	while(!q.empty()){
		node now=q.front();
		q.pop();
		
		if(now.a==c||now.b==c){//细节成败,是对c 
			printf("%d\n",now.step);
			print(now);
			return; 
		}
		
		node nex;
		nex.sa=now.a;
		nex.sb=now.b;
		nex.step=now.step+1; 
		
		//0:FILL(1)
		if(nex.sa<a){
			nex.a=a;
			nex.b=nex.sb;
			push(nex,0);
		}
		
		//1:FILL(2)
		if(nex.sb<b){
			nex.a=nex.sa;
			nex.b=b;
			push(nex,1);
		}
		
		//2:DROP(1)
		if(nex.sa){
			nex.a=0;
			nex.b=nex.sb;
			push(nex,2);
		}
		
		//3:DROP(2)
		if(nex.sb){
			nex.a=nex.sa;
			nex.b=0;
			push(nex,3);
		}
		
		//4:POUR(1,2)
		if(nex.sa){
			if(nex.sa<=(b-nex.sb)){
				nex.a=0;
				nex.b=nex.sa+nex.sb;
			}else{
				nex.a=nex.sa-(b-nex.sb);
				nex.b=b;
			}
			push(nex,4);
			
		}

		//5:POUR(2,1)
		if(nex.sb){
			if(nex.sb<=(a-nex.sa)){
				nex.b=0;
				nex.a=nex.sa+nex.sb;
			}else{
				nex.b=nex.sb-(a-nex.sa);
				nex.a=a;
			}
			push(nex,5);
		}
		
	}
	
	printf("impossible\n");
}

int main()
{ 
	scanf("%d%d%d",&a,&b,&c);
	bfs();
    return 0;
}

复习:
5/19
剪枝bfs
注意啦,刚开始一个小时一团糟,推倒重写。。
模拟题,数据结构先定好
各操作对什么数据起作用,先纵观全局想好
queue里放什么
各操作怎么安排
递归输出
不要忘了向queue里加
初始化怎么做…
这种各处联动的
一定要先把握好大局,才能写
不然临时改这改那,都乱了

比较吃力
但还是两小时一遍AC了,0ms

#include<stdio.h>
#include<queue>
using namespace std;
#ifdef LOCAL
FILE*fp=freopen("text.in","r",stdin);
#endif
#define N 103
struct Node{
	int a,b,cnt,vis,pa,pb,o1,o2,o3;//父 1填2倒3转 1从a2从b 若倒则有o3 
}s[N][N];//分别是va,vb 
queue<Node>q;
int a,b,c;
Node te;
void add(Node te){
	if(s[te.a][te.b].vis==0)q.push(s[te.a][te.b]=te);//最后忘记赋值就不好了 
}
void fd(int x,Node te,int flag){
	//a,b,o1,o2,o3
	te.o1=flag;
	te.o2=x;
	if(x==1){
		if(flag==1)te.a=a;
		else if(flag==2)te.a=0;
		else {
			te.o3=(x==1?2:1);
			int t=(b-te.b);
			if(te.a>t){
				te.b=b;
				te.a-=t;
			}else{
				te.b+=te.a;
				te.a=0;
			}
		}
	}else{
		if(flag==1)te.b=b;
		else if(flag==2)te.b=0;
		else{
			te.o3=(x==1?2:1);
			int t=a-te.a;
			if(te.b>t){
				te.b-=t;
				te.a=a;
			}else{
				te.a+=te.b;
				te.b=0;
			}
		}
	}
	add(te);
}
void print(Node te){
	if(te.a==0&&te.b==0)return ;
	print(s[te.pa][te.pb]);
	if(te.o1==1){
		printf("FILL(%d)\n",te.o2);
	}else if(te.o1==2){
		printf("DROP(%d)\n",te.o2);
	}else if(te.o1==3){
		printf("POUR(%d,%d)\n",te.o2,te.o3);
	}
}
int main(){
	scanf("%d%d%d",&a,&b,&c);//3 5 2
	s[0][0].vis=1,s[0][0].cnt=0,s[0][0].pa=s[0][0].pb=-1,s[0][0].a=s[0][0].b=0;
	q.push(s[0][0]);
	int flag=-1;
	Node te;
	while(!q.empty()){
		te=q.front();q.pop();
		if(te.a==c||te.b==c){
			flag=1;
			break;
		}
		te.pa=te.a;
		te.pb=te.b;
		te.cnt++;
		fd(1,te,1);
		fd(2,te,1);
		fd(1,te,2);
		fd(2,te,2);
		fd(1,te,3);
		fd(2,te,3);
	}
	if(flag==-1){
		printf("impossible\n");
	}else{
		printf("%d\n",te.cnt);
		print(te);
	}
	return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值