题解 P3139 【[USACO16FEB]牛奶桶Milk Pails】
NaVi_Awson · · 题解
可以不用dp,dfs和bfs也是可以的;
首先 dfs:f[i][j]表示两桶量分别为i,j是否出现过,就可以剪枝;
附上dfs代码:
#include<cstdio>
#include<iostream>
#include<cmath>
#include<cstdlib>
#include<cstring>
#include<string>
#include<algorithm>
using namespace std;
int x,y,k,m;
bool f[105][105];
int ans=1e9;
void dfs(int xn,int yn,int kn)
{
if ((f[xn][yn]==1)||(kn-1>k)) return;
f[xn][yn]=1;
ans=min(ans,abs(m-xn-yn));
dfs(x,yn,kn+1);
dfs(xn,y,kn+1);
dfs(0,yn,kn+1);
dfs(xn,0,kn+1);
if(x-xn<=yn) dfs(x,yn-(x-xn),kn+1);
else dfs(xn+yn,0,kn+1);
if(y-yn<=xn) dfs(xn-(y-yn),y,kn+1);
else dfs(0,xn+yn,kn+1);
f[xn][yn]=0;
return;
}
int main()
{
scanf("%d%d%d%d",&x,&y,&k,&m);
dfs(0,0,1);
cout<<ans<<endl;
return 0;
}
其次bfs:思路差不多;c[i][j]表示得到第一个杯子i升,第二个杯子j升,最小的操作次数,也就是在搜索树中层数 初始(0,0)入队,两个杯子中的容量都是0
取出队列首元素:(p,q)
考虑子结点,任意一个杯子倒空,任意一个杯子装满,从一个杯子倒入另一个杯子
bfs代码就不贴了(其实我懒)