题目通道
AC代码
#include<iostream>
#include<queue>
#include<cstring>
#include<string>
#include<sstream>
#include<map>
#include<vector>
#include<cstdio>
#include<iostream>
#include<cmath>
#include<algorithm>
#include<cstdlib>
#include<stack>
#include<ctime>
using namespace std;
#define rep(i,aa,bb) for(register int i=aa;i<=bb;i++)
#define rrep(i,aa,bb) for(register int i=aa;i>=bb;i--)
#define LL long long
#define eps 0.000001
#define inf 0x3f3f3f3f
#define exp 0.000001
#define pai 3.141592654
#define random(x) rand()%(x)
#define lowbit(x) x&(-x)
inline int read()
{
int x=0,y=1;char a=getchar();while ( a>'9' || a<'0'){if ( a=='-')y=-1;a=getchar();}
while ( a>='0' && a<='9' ){ x=10*x+a-'0'; a=getchar();}return x*y;
}
#define N 209
bool vis[N][N];
struct node {
int a,b,step; int las,lasdo;
};
struct node q[N];
int head = 1; int tail = 1;
int A,B,C;
void init(){
memset(vis,0,sizeof(vis));
}
void print(int st){
stack<int> R ;
for (int i = st; i ; i = q[i].las)
R.push(q[i].lasdo);
while ( R.empty() == 0 ){
int k = R.top();
R.pop();
switch(k)
{
case 1:cout<<"FILL(1)"<<endl;break;
case 2:cout<<"FILL(2)"<<endl;break;
case 3:cout<<"DROP(1)"<<endl;break;
case 4:cout<<"DROP(2)"<<endl;break;
case 5:cout<<"POUR(1,2)"<<endl;break;
case 6:cout<<"POUR(2,1)"<<endl;break;
}
}
}
void bfs(){
node now,nex ;
now.a = now.b = now.step = now.las = 0;
q[tail] = now;
tail++;
vis[0][0] = 1;
while ( head < tail ){
now = q[head];
++head;
if ( now.a == C || now.b == C ){
printf("%d\n",now.step);
print(head-1);
return ;
}
for (int ai = 1; ai <= 6; ai++){
switch(ai){
// fill a
case 1:
if ( now.a != A && !vis[A][now.b] ){
vis[A][now.b] = 1;
nex.a = A;
nex.b = now.b;
nex.step = now.step + 1;
nex.las = head-1;
nex.lasdo = ai;
q[tail] = nex;
tail++;
}
break;
// fill b
case 2:
if ( now.b != B && !vis[now.a][B] ){
vis[now.a][B] = 1;
nex.a = now.a;
nex.b = B;
nex.step = now.step + 1;
nex.las = head-1;
nex.lasdo = ai;
q[tail] = nex;
tail++;
}
break;
// drop a
case 3:
if ( now.a != 0 && !vis[0][now.b] ){
vis[0][now.b] = 1;
nex.a = 0;
nex.b = now.b;
nex.step = now.step + 1;
nex.las = head-1;
nex.lasdo = ai;
q[tail] = nex;
tail++;
}
break;
// drop b
case 4:
if ( now.b != 0 && !vis[now.a][0] ){
vis[now.a][0] = 1;
nex.a = now.a;
nex.b = 0;
nex.step = now.step + 1;
nex.las = head-1;
nex.lasdo = ai;
q[tail] = nex;
tail++;
}
break;
// a pour b
case 5:
if ( now.b != B && now.a != 0 && now.b+now.a >= B && !vis[now.a-(B-now.b)][B] ){
vis[now.a-(B-now.b)][B] = 1;
nex.a = now.a+now.b - B;
nex.b = B;
nex.step = now.step + 1;
nex.las = head-1;
nex.lasdo = ai;
q[tail] = nex;
tail++;
}
else if ( now.b != B && now.a != 0 && now.b+now.a < B && !vis[0][now.a+now.b] ){
vis[0][now.a+now.b] = 1;
nex.a = 0;
nex.b = now.a+now.b;
nex.step = now.step + 1;
nex.las = head-1;
nex.lasdo = ai;
q[tail] = nex;
tail++;
}
break;
// b pour a
case 6:
if ( now.a != A && now.b != 0 && now.b+now.a >= A && !vis[A][now.b+now.a-A] ){
vis[A][now.b+now.a-A] = 1;
nex.a = A ;
nex.b = now.b+now.a-A;
nex.step = now.step + 1;
nex.las = head-1;
nex.lasdo = ai;
q[tail] = nex;
tail++;
}
else if ( now.a != A && now.b != 0 && now.b+now.a < A && !vis[now.b+now.a][0] ){
vis[now.b+now.a][0] = 1;
nex.a = now.b+now.a;
nex.b = 0;
nex.step = now.step + 1;
nex.las = head-1;
nex.lasdo = ai;
q[tail] = nex;
tail++;
}
break;
}
}
}
cout<<"impossible"<<endl;
}
int main()
{
// freopen("data.txt","r",stdin);
// srand((int)time(0));
// std::ios::sync_with_stdio(false);
init();
A = read(); B = read(); C = read();
bfs();
return 0;
}
题目分析
简单bfs加队列,多给两个变量记录操作和上次的结点。
记录操作 lasdo 从哪次操作过来。
上次结点 las 从哪个结点过来。
利用栈处理,实现顺序倒转。
解释为什么ipossible
a,b状态量只会在一定的集合内变化。
vis记录使得无法重新入队。这时,a,b,的状态量会在一定集合内变化,当所有集合内都找不到对应的c值时,此时队列为空,就是无解的情况。
网上博客代码
有点错,当C == 0 时出错。POJ 没有那么强的数据。
#include <iostream>
#include <algorithm>
using namespace std;
#include <cstring>
#include <queue>
#include <stack>
struct cup
{
int x, y;
int step;
int flag;//标记操作
cup *pre;//记录路径
};
queue<cup>Q;
stack<int>R;
int a, b, e;
int vis[117][117]={0};//标记当前状态是否到达过
int ans;
void BFS(int x, int y)
{
cup c;
cup t[317];//目前瓶子里剩余的水量
c.x = 0, c.y = 0;
c.flag = 0;
c.pre = NULL;
c.step = 0;
Q.push(c);
vis[x][y] = 1;
int count = -1;
while(!Q.empty())
{
count++;
t[count] = Q.front();
Q.pop();
for(int i = 1; i <= 6; i++)
{
switch(i)
{
case 1: //fill a
c.x = a;
c.y = t[count].y;
c.flag = 1;
break;
case 2: //fill b
c.x = t[count].x;
c.y = b;
c.flag = 2;
break;
case 3: //drop a
c.x = 0;
c.y = t[count].y;
c.flag = 3;
break;
case 4: //drop b
c.x = t[count].x;
c.y = 0;
c.flag = 4;
break;
case 5: //pour a to b
if(t[count].x > b-t[count].y)
{
c.x = t[count].x-(b-t[count].y);
c.y = b;
}
else
{
c.x = 0;
c.y = t[count].y+t[count].x;
}
c.flag = 5;
break;
case 6: //pour b to a
if(t[count].y > a-t[count].x)
{
c.y = t[count].y - (a-t[count].x);
c.x = a;
}
else
{
c.x = t[count].x+t[count].y;
c.y = 0;
}
c.flag = 6;
break;
}
if(vis[c.x][c.y])
continue;
vis[c.x][c.y] = 1;
c.step = t[count].step+1;
c.pre = &t[count];
if(c.x == e || c.y == e)
{
ans = c.step;
while(c.pre)
{
R.push(c.flag);
c = *c.pre;
}
return;
}
Q.push(c);
}
}
}
void print()
{
while(!R.empty())
{
int i = R.top();
R.pop();
switch(i)
{
case 1:cout<<"FILL(1)"<<endl;break;
case 2:cout<<"FILL(2)"<<endl;break;
case 3:cout<<"DROP(1)"<<endl;break;
case 4:cout<<"DROP(2)"<<endl;break;
case 5:cout<<"POUR(1,2)"<<endl;break;
case 6:cout<<"POUR(2,1)"<<endl;break;
}
}
}
int main()
{
freopen("data.txt","r",stdin);
cin >>a>>b>>e;
BFS(0,0);
if(ans == 0)
cout<<"impossible"<<endl;
else
{
cout<<ans<<endl;
print();
}
return 0;
}
对拍实验。
我的代码保存为 137.cpp
网络上的代码保存为 137Ac.cpp
另外写一下的造数据代码 data.cpp
#include<iostream>
#include<queue>
#include<cstdio>
#include<algorithm>
#include<cstdlib>
#include<stack>
#include<ctime>
using namespace std;
#define random(x) rand()%(x)
inline int read()
{
int x=0,y=1;char a=getchar();while ( a>'9' || a<'0'){if ( a=='-')y=-1;a=getchar();}
while ( a>='0' && a<='9' ){ x=10*x+a-'0'; a=getchar();}return x*y;
}
#define N 100009
int main()
{
// freopen("1.txt","r",stdin);
srand((int)time(0));
std::ios::sync_with_stdio(false);
int a,b,c;
c = random(50);
b = random(50);
a = random(50);
printf("%d %d %d\n",a,b,c);
return 0;
}
最后是对拍代码(随意取名但是不要取 fc ,否则会影响dos命令)
#include<iostream>
#include<queue>
#include<cstdio>
#include<algorithm>
#include<cstdlib>
#include<stack>
#include<ctime>
using namespace std;
#define random(x) rand()%(x)
inline int read()
{
int x=0,y=1;char a=getchar();while ( a>'9' || a<'0'){if ( a=='-')y=-1;a=getchar();}
while ( a>='0' && a<='9' ){ x=10*x+a-'0'; a=getchar();}return x*y;
}
#define N 100009
int main()
{
// freopen("1.txt","r",stdin);
srand((int)time(0));
std::ios::sync_with_stdio(false);
int a,b,c;
c = random(50);
b = random(50);
a = random(50);
printf("%d %d %d\n",a,b,c);
return 0;
}