UVA10603 倒水问题

老师比赛时的第一题,比较简单,但多测不清空,亲人两行泪(⊙o⊙) 得了70分...

题目描述

假设有一个 6 升的杯子装满水,还各有一个 3 升和 1 升的空杯子,三个杯子均没有刻度。在不使用其他道具的情况下,是否可以量出 4 升的水呢?方法如下图所示。
注意:由于没有刻度,用杯子 x 给杯子 y 倒水时,必须一直持续到把杯子 y 倒满,或者把杯子 x 倒空,不能中途停止。
你的任务是,编写一个程序,解决一般性的问题:给定三个杯子的容量 a,b,c,最初只有第三个杯子装满了 c 升水,其他两个是空的。最少需要倒多少升水才能让某个杯子中恰好有 d 升水呢?如果无法做到恰好 d 升,就让某个杯子里的水为 d' 升,其中 d'<d 且尽量接近 d。要求输出最少的倒水量和目标水量(d 或者 d')。

输入格式

第一行一整数 t(t=20),表示数据组数。每组数据:
一行四个整数 a,b,c,d(1≤a,b,c,d≤200)。

输出格式

每组数据一行两个整数,分别表示倒水总量和目标水量。

输入输出样例

输入

2
2 3 4 2
96 97 199 62

输出

2 2
9859 62

数据规模

20% 的数据,n≤200;
40% 的数据,n≤5*103;
50% 的数据,n≤104;
100% 的数据,3≤n≤105,|xi|,|yi|≤104。

此题比较简单时间限制3.00s 暴力即可,自己看代码吧~:

#include<bits/stdc++.h>
using namespace std;
long long t,a,b,c,d,y=LONG_LONG_MAX,g=LONG_LONG_MAX,k;
long long x[205][205][205];//剪枝数组
void dfs(long long aa,long long bb,long long cc,long long dd)//暴力dfs
{
	if(x[aa][bb][cc]&&x[aa][bb][cc]<=dd)return;//剪枝,为什么是dd是因为深搜容易找不到最少的倒水量,所以要判断一下是否减枝
	if(x[aa][bb][cc]==0)x[aa][bb][cc]=dd;//没找过就直接标记
	else x[aa][bb][cc]=min(x[aa][bb][cc],dd);//最少的倒水量
	if(d>=aa&&y>d-aa||d>=aa&&y==d-aa&&dd<g)//记录最优解aa
	{
		y=abs(aa-d);
		k=aa;
		g=dd;
	}
	if(d>=bb&&y>d-bb||d>=bb&&y==d-bb&&dd<g)//记录最优解bb
	{
		y=abs(bb-d);
		k=bb;
		g=dd;
	}
	if(d>=cc&&y>d-cc||d>=cc&&y==d-cc&&dd<g)//记录最优解cc
	{
		y=abs(cc-d);
		k=cc;
		g=dd;
	}
	if(aa)//从aa倒到其他
	{
		if(bb!=b)
		{
			if(b-bb>=aa)
			{
				dfs(0,bb+aa,cc,dd+aa);
			}
			else
			{
				dfs(aa-(b-bb),b,cc,dd+(b-bb));
			}
		}
		if(cc!=c)
		{
			if(c-cc>=aa)
			{
				dfs(0,bb,cc+aa,dd+aa);
			}
			else
			{
				dfs(aa-(c-cc),bb,c,dd+(c-cc));
			}
		}
	}
	if(bb)//从bb倒到其他
	{
		if(aa!=a)
		{
			if(a-aa>=bb)
			{
				dfs(aa+bb,0,cc,dd+bb);
			}
			else
			{
				dfs(a,bb-(a-aa),cc,dd+(a-aa));
			}
		}
		if(cc!=c)
		{
			if(c-cc>=bb)
			{
				dfs(aa,0,cc+bb,dd+bb);
			}
			else
			{
				dfs(aa,bb-(c-cc),c,dd+(c-cc));
			}
		}
	}
	if(c)//从cc倒到其他
	{
		if(aa!=a)
		{
			if(a-aa>=cc)
			{
				dfs(aa+cc,bb,0,dd+cc);
			}
			else
			{
				dfs(a,bb,cc-(a-aa),dd+(a-aa));
			}
		}
		if(bb!=b)
		{
			if(b-bb>=cc)
			{
				dfs(aa,bb+cc,0,dd+cc);
			}
			else
			{
				dfs(aa,b,cc-(b-bb),dd+(b-bb));
			}
		}
	}
}
int main(){
	scanf("%lld",&t);
	while(t--)
	{
		y=g=LONG_LONG_MAX;
		memset(x,1,sizeof(x));//这就是考试时的30分啊~
		k=0;
		scanf("%lld%lld%lld%lld",&a,&b,&c,&d);
		dfs(0,0,c,0);
		printf("%lld %lld\n",g,k);
	}
	
	return 0;
}

欢迎大家在评论区开喷

posted @ 2026-01-23 13:36  PLJZ  阅读(3)  评论(0)    收藏  举报