这个题···一开始写T了,后来想出来了判断重复的方法,然后就过了。
思路就是用1-6分别记录每个不同的操作,然后每个结构体里带个栈(写的时候我以为会爆内存)
然后用一个函数判断组合数是否重复出现就可以了,这个函数自己乱写的。
AC代码
#include<iostream>
#include<vector>
#include<cstdio>
#include<string>
#include<cstring>
#include<queue>
using namespace std;
#define ll long long
#define up(i,a,n) for(int i=a;i<=n;i++)
int a,b,c;
struct node
{
int cnt;
int A,B;
vector<int>q;
}s;
bool vis[200000];
int f(int x,int y)
{
return x*101+y*13+7;//瞎写的二元单调函数
}
node bfs(node aa)
{
queue<node>q;
q.push(aa);
node sss;
sss.cnt=-1;
while(!q.empty())
{
node ss=q.front();q.pop();
if(!vis[f(ss.A,ss.B)])continue;
vis[f(ss.A,ss.B)]=false;
if(ss.A==c||ss.B==c)return ss;
ss.cnt++;
if(ss.A!=0)//把1抽干
{
node ssa=ss;
ssa.A=0;
ssa.q.push_back(1);
q.push(ssa);
}
if(ss.B!=0)//把2抽干
{
node ssa=ss;
ssa.B=0;
ssa.q.push_back(2);
q.push(ssa);
}
if(ss.A!= a)//把1填满
{
node ssa=ss;
ssa.A=a;
ssa.q.push_back(3);
q.push(ssa);
}
if(ss.B!=b)//把2填满
{
node ssa=ss;
ssa.B=b;
ssa.q.push_back(4);
q.push(ssa);
}
if(ss.B+ss.A<=b) //把1倒入2
{
node ssa=ss;
ssa.A=0;
ssa.B=ss.A+ss.B;
ssa.q.push_back(5);
q.push(ssa);
}
if(ss.B+ss.A>b)//把1倒入2
{
node ssa=ss;
ssa.A=ss.A-(b-ss.B);
ssa.B=b;
ssa.q.push_back(5);
q.push(ssa);
}
if(ss.B+ss.A<=a)//把2倒入1
{
node ssa=ss;
ssa.A=ss.A+ss.B;
ssa.B=0;
//printf("%d %d\n",ss.A,ss.B);
ssa.q.push_back(6);
q.push(ssa);
}
if(ss.A+ss.B>a)//把2倒入1
{
node ssa=ss;
ssa.B=ss.B-(a-ss.A);
ssa.A=a;
//printf("%d %d\n",ssa.A,ssa.B);
ssa.q.push_back(6);
q.push(ssa);
}
}
return sss;
}
void print()
{
if(s.cnt==-1)printf("impossible\n");
else
{
printf("%d\n",s.cnt);
for(int i=0;i<s.q.size();i++)
{
switch(s.q[i])
{
case 1:printf("DROP(1)\n");break;
case 2:printf("DROP(2)\n");break;
case 3:printf("FILL(1)\n");break;
case 4:printf("FILL(2)\n");break;
case 5:printf("POUR(1,2)\n");break;
case 6:printf("POUR(2,1)\n");break;
}
}
}
}
int main()
{ memset(vis,true,sizeof(vis));
scanf("%d %d %d",&a,&b,&c);
s.A=0;
s.B=0;
s.cnt=0;
s=bfs(s);
print();
}