P1432 倒水问题- 普及+/提高(好好理解!)

P1432 倒水问题

题意:就是有俩被子容量a b,让你想办法让b里面装n些水。然后有六种操作
在这里插入图片描述
输出次数和过程。
思路:刚开始我以为就观察a n的关系来写就行了,唉写了半天40分
错误代码:

/*
	3 5 4   n>a 把b倒满 然后不断地进行b倒给a,
	          满了把a倒空,然后再来重复,知道a b其中一个等于n
	用了六步
	1.把b倒满。 a=0,b=5,
	2.b倒给a。  a=3,b=2; 
	3.把a倒空   a=0,b=2;
	4.b倒给a    a=2,b=0
	5.倒满b     a=2 b=5;
	6.b倒给a    a=3  b=4;
	*/
	/*
	5  7  3    a>n         把a倒满 然后不断地进行a倒给b,满了把b倒空,
	                       然后再来重复,知道a b其中一个等于n
	用了6
	1.把a倒满 a=5 b=7
	2.把a倒给b  a=0 b=5
	3.把a倒满  a=5,b=5;
	4.把a倒给b  a=3,b=7;
	5.把b倒空  a=3,b=0
	6.把a倒给b  a=0,b=3;
	*/
#include <iostream>
#include <cstdio>
#include <cmath>
#include <string>
#include <cstring>
#include <stack>
#include <algorithm>
#include <iomanip>
#include <map>
#include <queue>
#include <vector>
#include <set>
const int inf = 0x3f3f3f3f;//1061109567
typedef long long ll;
using namespace std;
int v[100000];
void f(int a, int b, int n)
{
	int aa = 0, bb = 0;
	int s = 0;
	if (n > a) //n > a 把b倒满 然后不断地进行b倒给a,满了把a倒空,然后再来重复,知道a b其中一个等于n
	{
		v[++s] = 2;bb = b;
		while (aa !=n&&bb!= n)
		{
			v[++s] = 5;//b倒a
			if (bb >= a-aa)
			{
				bb = bb - (a-aa);
				aa=a;
			}
			else
			{
				aa+=bb; bb = 0;
			}
			if (aa == n||bb == n) break;
			if (bb == 0)
			{
				bb = b;
				v[++s] = 2;
			}
			if (aa == a)
			{
				v[++s] = 3;
				aa = 0;
			}
		}
	}
	else if (n< a)
	{
		v[++s] = 1; aa = a;
		while (aa != n && bb != n)
		{
			v[++s] =6;//a倒b
			if (aa >=b -bb)
			{
				aa = aa - (b - bb);
				bb = b;
			}
			else
			{
				bb += aa; aa = 0;
			}
			if (aa == n || bb == n) break;
			if (aa == 0)
			{
				aa = a;
				v[++s] =1;
			}
			if (bb == b)
			{
				v[++s] =4;
				bb = 0;
			}
		}

	}
	if (aa == n)
	{
		v[++s] = 4;
		v[++s] = 6;
	}
	cout << s << " ";
	for (int i = 1; i <=s; i++)
		cout << v[i] << " ";
	cout << endl;
}
int main()
{
	int t; cin >> t;
	while (t--)
	{
		int a, b, n; cin >> a >> b >> n;
		if (a == n)
		{
			cout << 2 << " ";
			cout << 1 << " " << 6 << endl; continue;
		}
		else if (b == n)
		{
			cout << 1 << " " << 2 << endl; continue;
		}
		f(a, b, n);	
	}
	
}

正确思路:用dfs来做!!!!
设立数组
int x[6][3] =
{
{A, b, 1},//x[0][0] x[0][1] x[0][2]
{a,B, 2},//x[1][0] x[1][1] x[1][2]
{0, b, 3},//x[2][0] x[2][1] x[2][2]
{a, 0, 4},
{tmp1, a+b-tmp1, 5},
{a+b-tmp2, tmp2, 6}
};
vis表示状态 now数组表示当前步 ,best 表示好的方案步.
用dfs搜索。

#include <iostream>
#include <cstdio>
#include <cmath>
#include <string>
#include <cstring>
#include <stack>
#include <algorithm>
#include <iomanip>
#include <map>
#include <queue>
#include <vector>
#include <set>
const int inf = 0x3f3f3f3f;//1061109567
typedef long long ll;
using namespace std;
int A, B, n;
bool vis[3010][3010];
int now[100010], best[100010], k;
void dfs(int a, int b, int c) 
{
    if (c >= k) return;
    if (b == n)
    {
        memcpy(best, now, sizeof now);
        k = c;
        return;
    }
  int tmp1, tmp2;
    if (a + b > A)
        tmp1 = A;
    else tmp1 = a + b;
    if (a + b > B)
        tmp2 = B;
    else tmp2 = a + b;
    int x[6][3] =
    {
    {A, b, 1},//x[0][0] x[0][1]  x[0][2]
    {a,B, 2},//x[1][0]  x[1][1]  x[1][2]
     {0, b, 3},//x[2][0] x[2][1] x[2][2]
    {a, 0, 4},
    {tmp1, a+b-tmp1, 5},
    {a+b-tmp2, tmp2, 6}
    };
    vis[a][b] = 1;
    for (int i = 0; i < 6; i++) 
    {
        if (!vis[x[i][0]][x[i][1]]) //如果这个vis[a][b]没弄过
        {
            now[c] = x[i][2];//当前步数到哪一步了 x[i][2] 是步;
            dfs(x[i][0],x[i][1],c+1);
        }
    }
    vis[a][b] = 0;
}
int main()
{
    int t;
    cin >> t;
    while (t--) 
    {
        memset(vis, 0, sizeof vis);
        k = inf;
        cin >> A >> B >> n;
        dfs(0, 0, 0);
        cout << k;
        for (int i = 0; i < k; i++)
            cout << " " << best[i];
        cout << endl;
    }
}

      
            
 
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值