Date:2022.02.06
题意:
给你两个罐子,容积分别为 A 升和 B 升。
现在,你可以进行如下三种操作:
1.FILL(i),将罐子 i(1≤i≤2)灌满水。
2.DROP(i),将罐子 i(1≤i≤2)清空。
3.POUR(i,j),将罐子 i 中的水倒向罐子 j,直到罐子 i 空了或罐子 j 满了为止。
请问,至少多少次操作后,可以使得其中一个罐子里恰好有 C 升水。
输入格式
共一行,三个整数 A,B,C。
输出格式
如果无解,则输出一行 impossible 即可。
否则,第一行输出一个整数,表示最少操作次数。
随后按顺序每行输出一个操作指令,格式参考题面。
数据范围
1≤A,B,C≤100,
C≤max(A,B)。
输入样例:
3 5 4
输出样例:
6
FILL(2)
POUR(2,1)
DROP(1)
POUR(2,1)
FILL(2)
POUR(2,1)
思路:最少次数显然是BFS,有些恶心的是存路径。这里也写了一下DFS。
①DFS:过19个点
#include <iostream>
#include <algorithm>
#include <cstring>
#define x first
#define y second
using namespace std;
const int N = 210;
typedef pair<int, int> PII;
PII q[N],ans[N];
int a, b;
int n, m, k;
int cnt, res = 0x3f3f3f3f;
bool st[N][N];
void dfs(int x,int y)
{
if(cnt>res) return;
if(x==k||y==k)
{
if(cnt<res)
{
res=cnt;
for(int i=1;i<=res;i++) ans[i]=q[i];
}
return;
}
for(int i=1;i<=2;i++)
for(int j=1;j<=3;j++)
{
int ix=x,iy=y;
if(i==1&&j==1&&!st[n][y]) ix=n;
else if(i==1&&j==2&&!st[0][y]) ix=0;
else if(i==1&&j==3&&!st[max(x-m+y,(int)0)][min(y,x+y)])
{ix=max(x-m+y,(int)0);iy=min(m,x+y);}
else if(i==2&&j==1&&!st[x][m]) iy=m;
else if(i==2&&j==2&&!st[x][0]) iy=0;
else if(i==2&&j==3&&!st[min(n,x+y)][max(x-n+y,(int)0)])
{ix=min(n,x+y);iy=max(x-n+y,(int)0);}
else continue;//否则会直接爆栈
q[++cnt]={i,j};
st[ix][iy]=true;
dfs(ix,iy);
cnt--;st[ix][iy]=false;
}
}
int main()
{
cin >> n >> m >> k;
st[0][0] = true;
dfs(0, 0);
if (res == 0x3f3f3f3f) puts("impossible");
else
{
cout<<res<<endl;
for(int i=1;i<=res;i++) //cout<<ans[i].y<<' '<<ans[i].x<<endl;
if(ans[i].y==1) printf("FILL(%d)\n",ans[i].x);
else if(ans[i].y==2) printf("DROP(%d)\n",ans[i].x);
else if(ans[i].y==3)
{
int xx=0,yy=0;
if(ans[i].x==1) {xx=1;yy=2;}
else {xx=2;yy=1;}
printf("POUR(%d,%d)\n",xx,yy);
}
}
return 0;
}
②BFS:AC
#include <iostream>
#include <algorithm>
#include <cstring>
#include <queue>
#define x first
#define y second
using namespace std;
const int N = 210;
typedef pair<int, int> PII;
int n, m, k,d[N][N],dd=1e9;
vector<PII>ans;
struct node
{
int x,y;
vector<PII>v;
}s[N];
void bfs()
{
memset(d,-1,sizeof d);
queue<node>q;d[0][0]=0;
vector<PII>vv;vv.push_back({0,0});q.push({0,0,vv});
while(q.size())
{
node t=q.front();q.pop();
vector<PII>vvv=t.v;
if(t.x==k||t.y==k)
{
if(dd>d[t.x][t.y])
{
dd=d[t.x][t.y];
ans=vvv;
}
return;
}
for(int i=1;i<=2;i++)
for(int j=1;j<=3;j++)
{
vvv=t.v;
if(i==1&&j==1&&d[n][t.y]==-1)
{
vvv.push_back({i,j});
q.push({n,t.y,vvv});
d[n][t.y]=d[t.x][t.y]+1;
}
else if(i==1&&j==2&&d[0][t.y]==-1)
{
vvv.push_back({i,j});
q.push({0,t.y,vvv});
d[0][t.y]=d[t.x][t.y]+1;
}
else if(i==1&&j==3&&d[max(t.x-m+t.y,0)][min(m,t.x+t.y)]==-1)
{
vvv.push_back({i,j});
q.push({max(t.x-m+t.y,0),min(m,t.x+t.y),vvv});
d[max(t.x-m+t.y,0)][min(m,t.x+t.y)]=d[t.x][t.y]+1;
}
else if(i==2&&j==1&&d[t.x][m]==-1)
{
vvv.push_back({i,j});
q.push({t.x,m,vvv});
d[t.x][m]=d[t.x][t.y]+1;
}
else if(i==2&&j==2&&d[t.x][0]==-1)
{
vvv.push_back({i,j});
q.push({t.x,0,vvv});
d[t.x][0]=d[t.x][t.y]+1;
}
else if(i==2&&j==3&&d[min(n,t.x+t.y)][max(t.x-n+t.y,0)]==-1)
{
vvv.push_back({i,j});
q.push({min(n,t.x+t.y),max(t.x-n+t.y,0),vvv});
d[min(n,t.x+t.y)][max(t.x-n+t.y,0)]=d[t.x][t.y]+1;
}
}
}
}
int main()
{
cin >> n >> m >> k;
bfs();
if(dd==1e9) cout<<"impossible\n";
else cout<<dd<<endl;
for(int i=1;i<ans.size();i++)
{
if(ans[i].y==1) printf("FILL(%d)\n",ans[i].x);
else if(ans[i].y==2) printf("DROP(%d)\n",ans[i].x);
else
{
if(ans[i].x==2) printf("POUR(2,1)\n");
else printf("POUR(1,2)\n");
}
}
return 0;
}