题意:
给出两个桶,体积分别是A,B升。可以进行以下操作:
1. F I L L ( i ) FILL(i) FILL(i) 填满桶 i ( 1 ≤ i ≤ 2 ) i (1 ≤ i ≤ 2) i(1≤i≤2)
2. D R O P ( i ) DROP(i) DROP(i) 清空桶i
3. P O U R ( i , j ) POUR(i,j) POUR(i,j) 将桶i内液体倒入桶j;在这个操作之后,要么桶j满(可能桶i中会有液体剩余),要么桶i空的(桶内所有液体都被倒入桶j)
编写一个程序找出可能的最短的操作步骤,能够让其中一个桶内的液体达到c升。
输入:
A B C 数据范围: 1 − 100 1-100 1−100 并且 C ≤ m a x ( A , B ) C≤max(A,B) C≤max(A,B)
输出:
第一行:操作步数k
接下来k行: 若有多组答案,输出任意一种情况即可。
若无法实现操作,输出“impossible”
思路:
BFS,把每种情况不重不漏(也就是说要注意去重)得放进去,这里使用的一个二维数组记录的这一组数据有没有出现过。然后每组数据都带着一起走,所以用了结构体,cnt作为索引,flag数组作为一个关系链, f l a g [ c n t ] = t flag[cnt] = t flag[cnt]=t,意思就是当前这个索引是由当前得队头做操作得来的,也就是说距离它最近得上一个是t,就是cnt的上一个是t得意思,然后判断六种情况,注意还要判断范围不能大于最大容量不能小于0之类的。最后尤其要注意 i m p o s s i b l e impossible impossible的情况。
代码
//#include <iostream>
//#include <queue>
//#include <cstring>
//#include <algorithm>
//#include <cstdio>
//using namespace std;
//const int N = 150;
//int a, b, c;
//
//int d[N][N];
//
//struct name
//{
// int aa, bb;
// string s;//操作步骤
//}num[N];
//int flag[N];
//void bfs()
//{
// queue<int> q;
// q.push(0);
// for (int i = 0; i <= 149 ;i ++ )
// {
// for (int j = 0; j <= 149; j ++ )
// {
// d[i][j] = -1;
// }
// }
// d[0][0] = 0;
// int cnt = 1;
// while (!q.empty())
// {
// int t = q.front();
// cout << t << endl;
// q.pop();
// int a1 = num[t].aa;
// int b1 = num[t].bb;
// if (a1 == c || b1 == c)
// {
// vector<int> ans;
// int v = t;
// while (v != 0)
// {
// cout << v << " ";
// ans.push_back(v);
// v = flag[v];
// }
// cout << endl;
// for (int i = ans.size() - 1; i >= 0; i -- )
// {
// cout << num[ans[i]].s<< endl;
// }
// break;
// }
// int x, y; string ss = "";
//
// if (a1 < a) //填满A
// {
// x = a;
// y = b1;
// ss = "FILL(1)";
// if (d[x][y] == -1)
// {
// num[cnt].aa = x;
// num[cnt].bb = y;
// num[cnt].s = ss;
// q.push(cnt);
// cnt ++;
// d[x][y] = t; //记录一下上一步
// flag[cnt - 1] = t;cout<<cnt-1 <<ss<<"1: " << x << " " << y << " ";
// }
//
// }
//
// if (b1 < b) //填满B
// {
// x = a1;
// y = b;
// ss = "FILL(2)";
// if (d[x][y] == -1)
// {
// num[cnt].aa = x;
// num[cnt].bb = y;
// num[cnt].s = ss;
// q.push(cnt);
// cnt ++;
// d[x][y] = t; //记录一下上一步
// flag[cnt - 1] = t;cout<<cnt-1<<ss <<"2: " << x << " " << y << " ";
// }
//
// }
//
// if (a1 > 0) //清空A
// {
// x = 0;
// y = b1;
// ss = "DROP(1)";
// if (d[x][y] == -1)
// {
// num[cnt].aa = x;
// num[cnt].bb = y;
// num[cnt].s = ss;
// q.push(cnt);
// cnt ++;
// d[x][y] = t; //记录一下上一步
// flag[cnt - 1] = t; cout<<cnt-1<<ss <<"3: " << x << " " << y << " ";
// }
//
// }
//
// if (b1 > 0) //清空B
// {
// x = a1;
// y = 0;
// ss = "DROP(2)";
// if (d[x][y] == -1)
// {
// num[cnt].aa = x;
// num[cnt].bb = y;
// num[cnt].s = ss;
// q.push(cnt);
// cnt ++;
// d[x][y] = t; //记录一下上一步
// flag[cnt - 1] = t;cout<<cnt-1<<ss <<"4: " << x << " " << y << " ";
// }
//
// }
//
// if (a1 > 0 && b1 < b) //A-B
// {
// int p = b - b1;
// if (a1 < p)
// {
// x = 0;
// y = b1 + a1;
// }
// else
// {
// x = a1 - p;
// y = b;
// }
// ss = "POUR(1, 2)";
// if (d[x][y] == -1)
// {
// num[cnt].aa = x;
// num[cnt].bb = y;
// num[cnt].s = ss;
// q.push(cnt);
// cnt ++;
// d[x][y] = t; //记录一下上一步
// flag[cnt - 1] = t;cout<<cnt-1<<ss <<"5: " << x << " " << y << " ";
// }
//
// }
//
// if (a1 < a && b1 > 0) //B - A;
// {
// int p = a - a1;
// if (b1 < p)
// {
// x = 0;
// y = b1 + a1;
// }
// else
// {
// x = a;
// y = b1 - p;
// }
// ss = "POUR(2, 1)";
// if (d[x][y] == -1)
// {
// num[cnt].aa = x;
// num[cnt].bb = y;
// num[cnt].s = ss;
// q.push(cnt);
// cnt ++;
// d[x][y] = t; //记录一下上一步
// flag[cnt - 1] = t;cout<<cnt-1<<ss <<"6: " << x << " " << y << " ";
// }
//
// }
// cout << endl;
// }
//}
//
//int main()
//{
// cin >> a >> b >> c;
//
// num[0].aa = 0;
// num[0].bb = 0;
// bfs();
// cout << endl << endl;
// for (int i = 1; i <= 30 ; i ++ )
// {
// cout << num[i].aa << " " << num[i].bb << " " << num[i].s<< endl;
// }
// return 0;
//}
#include <iostream>
#include <queue>
#include <cstring>
#include <algorithm>
#include <cstdio>
using namespace std;
const int N = 200;
int d[N][N];
queue<int> q;
int cnt = 1;
int A, B, c;
int flag[N];
struct name{
int a, b;
string s;
}num[N];
bool f = 0;
void bfs()
{
memset(d, 0, sizeof d);
memset(flag, 0, sizeof flag);
d[0][0] = 1;
flag[0]=0;
q.push(0);
while (!q.empty())
{
int t = q.front();
q.pop();
if (num[t].a == c || num[t].b == c)
{
f = 1;
vector<int> ans;
int v = t;
while (v != 0)
{
ans.push_back(v);
v = flag[v];
}
cout << ans.size() << endl;
for (int j = ans.size() - 1; j >= 0; j -- )
{
cout << num[ans[j]].s << endl;
}
break;
}
//填满A
if(!d[A][num[t].b])
{
d[A][num[t].b]= 1;
num[cnt].a = A;
num[cnt].b = num[t].b;
num[cnt].s = "FILL(1)";
flag[cnt] = t;
q.push(cnt);
cnt ++;
}
//填满B
if(!d[num[t].a][B])
{
d[num[t].a][B] = 1;
num[cnt].a = num[t].a;
num[cnt].b = B;
num[cnt].s = "FILL(2)";
flag[cnt] = t;
q.push(cnt);
cnt ++;
}
//清空A
if(num[t].a != 0 && !d[0][num[t].b])
{
d[0][num[t].b] = 1;
num[cnt].a = 0;
num[cnt].b = num[t].b;
num[cnt].s = "DROP(1)";
flag[cnt] = t;
q.push(cnt);
cnt ++;
}
//清空B
if(!d[num[t].a][0] && num[t].b != 0)
{
d[num[t].a][0] = 1;
num[cnt].a = num[t].a;
num[cnt].b = 0;
num[cnt].s = "DROP(2)";
flag[cnt] = t;
q.push(cnt);
cnt ++;
}
//a - b
int p = A - num[t].a;
if (num[t].b != 0 && num[t].a != A)
{
if (p >= num[t].b && !d[num[t].a + num[t].b][0])
{
d[num[t].a + num[t].b][0] = 1;
num[cnt].a = num[t].a + num[t].b;
num[cnt].b = 0;
num[cnt].s = "POUR(2,1)";
flag[cnt] = t;
q.push(cnt);
cnt ++;
}
else if (p < num[t].b && !d[A][num[t].b - p])
{
d[A][num[t].b - p] = 1;
num[cnt].a = A;
num[cnt].b = num[t].b - p;
num[cnt].s = "POUR(2,1)";
flag[cnt] = t;
q.push(cnt);
cnt ++;
}
}
//b - a
if (num[t].a != 0 && num[t].b != B)
{
p = B - num[t].b;
if (p >= num[t].a && !d[0][num[t].a + num[t].b])
{
d[0][num[t].a + num[t].b] = 1;
num[cnt].a = 0;
num[cnt].b = num[t].a + num[t].b;
num[cnt].s = "POUR(1,2)";
flag[cnt] = t;
q.push(cnt);
cnt ++;
}
else if (p < num[t].a && !d[num[t].a - p][B])
{
d[num[t].a - p][B] = 1;
num[cnt].a = num[t].a - p;
num[cnt].b = B;
num[cnt].s = "POUR(1,2)";
flag[cnt] = t;
q.push(cnt);
cnt ++;
}
}
}
}
int main()
{
cin >> A >> B >> c;
bfs();
if (!f) cout << "impossible" << endl;
return 0;
}
总结:
说难也不难,就是很烦,很多细节要注意,要理清楚关系。