菜菜

  博客园  :: 首页  :: 新随笔  :: 联系 :: 订阅 订阅  :: 管理

题意:

给你三个杯子,a,b,c,没有刻度,刚开始c杯是满的,倒水的要求,要么倒出水的杯子倒空,要么倒入杯子倒满.

结果:

要求某个杯子内有d水量,并且倒出的水量最少,如果倒不出d水量,那么倒出d1(d1<d)水量,并且倒出的水量最少

解题思路:

总的水量为c,只要知道前俩个杯子的水量,那么第三个杯子的水量就确定了,所以,状态数最大只有a * b种,所以一个二维数组标记状态就够.

要求倒出的水量最少,那么使用优先队列,按照倒出的水量最少开始搜索.

初始化结点为(0,0,c),由这个结点开始往外扩展,此时倒出的水量为0,结果d为0,注意代码内有个特判,如果d >= c,那么最大的d就是c,倒出的水量为0

#include <iostream>
#include <stdio.h>
#include <memory.h>
#include <queue>

using namespace std;
const int NN = 201;
int a[3];
int d;
int maxD = -1;
int maxNum = 0;
//记录c1,c2,已知c1,c2,c3就可以确定
int vis[NN][NN];
class State
{
	public:
		int a[3];
		int waterNum;
		State()
				: waterNum(0)
		{
			a[0] = 0;
			a[1] = 0;
			a[2] = 0;
		}
		State(int d1, int d2, int d3, int w)
				: waterNum(w)
		{
			a[0] = d1;
			a[1] = d2;
			a[2] = d3;
		}
		bool operator ()(State& a, State& b)
		{
			return a.waterNum > b.waterNum;
		}
};
priority_queue<State, vector<State>, State> q;
void bfs()
{
	while (!q.empty())
	{
		State s = q.top();
		q.pop();
		for(int i = 0; i < 3; i++)
			for(int j = 0; j < 3; j++)
			{
				if(i == j || s.a[i] == 0)
					continue;
				//把水从i导入j中
				//要么i倒空,要么j倒满
				int dj = a[j] - s.a[j];
				if(dj == 0)
					//j是满的,不能倒
					continue;
				//i杯内的水量
				int di = s.a[i];
				//倒出的水量
				State ss(s.a[0], s.a[1], s.a[2], s.waterNum);
				if(dj > di)
				{
					//i杯倒空
					ss.waterNum = ss.waterNum + di;
					ss.a[i] = 0;
					ss.a[j] = ss.a[j] + di;
				}
				else
				{
					//j杯倒满
					ss.waterNum = ss.waterNum + dj;
					ss.a[i] = di - dj;
					ss.a[j] = ss.a[j] + dj;
				}
				if(vis[ss.a[0]][ss.a[1]])
					continue;
				//判断当前状态
				if(ss.a[i] <= d && ss.a[i] > maxD)
				{
					maxD = ss.a[i];
					maxNum = ss.waterNum;
				}
				if(ss.a[j] <= d && ss.a[j] > maxD)
				{
					maxD = ss.a[j];
					maxNum = ss.waterNum;
				}
				if(maxD == d)
					return;
				q.push(ss);
				vis[ss.a[0]][ss.a[1]] = 1;
			}
	}
}
void clear()
{
	while (!q.empty())
		q.pop();
	memset(vis, 0, sizeof(vis));
	maxNum = 0;
	maxD = 0;
}
int main()
{
	int num;
	cin >> num;
	while (num--)
	{
		clear();
		cin >> a[0] >> a[1] >> a[2] >> d;
		if(d >= a[2])
		{
			cout << 0 << " " << a[2] << endl;
			continue;
		}
		State state(0, 0, a[2], 0);
		q.push(state);
		vis[0][0] = 1;
		bfs();
		if(maxD == 0)
			cout << 0 << " " << 0 << endl;
		else
			cout << maxNum << " " << maxD << endl;
	}
	return 0;
}

  

 

posted on 2018-07-14 18:53  好吧,就是菜菜  阅读(254)  评论(0编辑  收藏  举报