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;
}
}