【BZOJ】4413: [Usaco2016 Feb]Milk Pails

Description

有两个桶大小为X和Y,开始都是空的。
有如下三种操作,最多操作K次。
①用倒满一个桶。
②倒空一个桶。
③把一个桶里的水倒到另一个桶里,直到一个桶空了或者另一个桶满了。(看哪种情况先发生)

给出要求的水量M.
最后你获得的水量是两个桶的水量之和M'。
求|M-M'|的最小值。

Input

一行,四个数X,Y,K,M.
1<=X,Y,K<=100
1<=M<=200

Output

输出一个数表示最小值。

Sample Input

14 50 2 32

Sample Output

18


题解:

   数据范围很善良的说……于是我们想到暴力。dp[i][j][k]表示修改i次,当前两个桶的水量分别为j和k的是否可行的状态。初始dp[0][0][0]=1(可行),于是对于每一个dp[i][][],尝试更新dp[i+1][][]是否可行。然后顺便维护一个ans就ok了。

  这个貌似叫做bool dp?

 

#include <iostream>
#include <cstdio>
#include <algorithm> 
using namespace std;
const int MAXN = 105;
bool dp[MAXN][MAXN][MAXN];
int x, y, K, m;
int main(int argc, char *argv[])
{
	int i, j, k;
	cin >> x >> y >> K >> m;                                                                                                
	int ans = 0;
	dp[0][0][0] = 1;
	for (i = 0; i <= K; i++)
	{
		for (j = 0; j <= x; j++)
			for (k = 0; k <= y;k++)
				if (dp[i][j][k] == 1)
				{
			if (abs(j +  k -m)<abs(ans-m))
			{
				ans = j + k;
				if (ans == m)
				{
					printf("%d\n", 0);
					exit(0);
				}
			}
			dp[i + 1][0][k] = 1;
			dp[i + 1][j][0] = 1;
			dp[i + 1][j][y] = 1;
			dp[i + 1][x][k] = 1;
			if (y - k>j) dp[i + 1][0][k + j] = 1;
			else dp[i + 1][k + j - y][y] = 1;
			if (k + j < x) dp[i + 1][k + j][0] = 1;
			else dp[i + 1][x][k + j - x] = 1;
				}
	}
	printf("%d\n", abs(ans - m));
	return 0;
}


 

posted @ 2016-10-24 16:29  BeyondW  阅读(301)  评论(0编辑  收藏  举报