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;
}