题意:三个杯子容量分别为a,b,c,现在c是满的,a和b是空的,两个杯子 i 向 j 倒水,要么 i 倒完了 j 还没满,要么 j 满了 i 还有剩余,问达到某个杯子水量为d时总共倒得最小水量是多少?如果不能达到d,找一个小于d并且离d最近的一个解。
思路:倒水问题,但题目要求的是总的到水量,所以在bfs时到达过的状态还要检查更新,可能当前我确实到达d了用了sum水量,但可能后面还有比sum更小的解。网上有很多代码都是错误的,很多就是错在这里。
代码:
#include <iostream> #include <functional> #include <cstdio> #include <cstring> #include <algorithm> #include <cmath> #include <string> #include <map> #include <stack> #include <vector> #include <set> #include <queue> #pragma comment (linker,"/STACK:102400000,102400000") #define pi acos(-1.0) #define eps 1e-6 #define lson rt<<1,l,mid #define rson rt<<1|1,mid+1,r #define FRE(i,a,b) for(i = a; i <= b; i++) #define FREE(i,a,b) for(i = a; i >= b; i--) #define FRL(i,a,b) for(i = a; i < b; i++) #define FRLL(i,a,b) for(i = a; i > b; i--) #define mem(t, v) memset ((t) , v, sizeof(t)) #define sf(n) scanf("%d", &n) #define sff(a,b) scanf("%d %d", &a, &b) #define sfff(a,b,c) scanf("%d %d %d", &a, &b, &c) #define pf printf #define DBG pf("Hi\n") typedef long long ll; using namespace std; #define INF 0x3f3f3f3f #define mod 1000000009 const int maxn = 202; const int MAXN = 2005; const int MAXM = 200010; const int N = 1005; struct Node { int sum; int val[3]; }; int vis[maxn][maxn];//判断状态是否被访问过 int a[3],d; int ans[maxn];//ans[i]记录杯子的水量达到i时总共转移的水量的最小值 void bfs() { Node st,now; memset(vis,0,sizeof(vis)); memset(ans,INF,sizeof(ans)); st.val[0]=0,st.val[1]=0,st.val[2]=a[2],st.sum=0; vis[0][0]=1; ans[0]=ans[a[2]]=0; queue<Node>Q; Q.push(st); while (!Q.empty()) { st=Q.front(); Q.pop(); for (int i=0;i<3;i++) //i向j里面倒水 { for (int j=0;j<3;j++) { if (i==j||st.val[i]==0||st.val[j]==a[j]) continue; now.val[0]=st.val[0]; now.val[1]=st.val[1]; now.val[2]=st.val[2]; now.sum=st.sum; int x=a[j]-now.val[j]; if (now.val[i]>=x) //i里面的水量可以把j倒满 { now.val[i]-=x; now.val[j]=a[j]; now.sum+=x; } else //需要把i倒完 { now.val[j]+=now.val[i]; now.sum+=now.val[i]; now.val[i]=0; } if (!vis[now.val[0]][now.val[1]]) //这个状态没有到达过 { vis[now.val[0]][now.val[1]]=1; for (int k=0;k<3;k++) //更新答案 if (ans[now.val[k]]>now.sum) ans[now.val[k]]=now.sum; Q.push(now); } else //虽然这个状态之前被访问了,但仍然需要检查是否可以得到更优解 { for (int k=0;k<3;k++) { if (ans[now.val[k]]>now.sum) { ans[now.val[k]]=now.sum; Q.push(now); } } } } } } } int main() { #ifndef ONLINE_JUDGE freopen("C:/Users/lyf/Desktop/IN.txt","r",stdin); #endif int i,j,t; scanf("%d",&t); while (t--) { scanf("%d%d%d%d",&a[0],&a[1],&a[2],&d); bfs(); for (i=d;i>=0;i--) { if (ans[i]<INF) { printf("%d %d\n",ans[i],i); break; } } } return 0; }
版权声明:本文为博主原创文章,未经博主允许不得转载。
原文地址:http://blog.csdn.net/u014422052/article/details/47605011