无脑博士的试管们(状态图的深度优先搜索)
无脑博士有三个容量分别是 A,B,CA,B,C 升的试管,A,B,CA,B,C 分别是三个从 11 到 2020 的整数,最初,AA 和 BB 试管都是空的,而 CC 试管是装满硫酸铜溶液的。有时,无脑博士把硫酸铜溶液从一个试管倒到另一个试管中,直到被灌试管装满或原试管空了。当然每一次灌注都是完全的。由于无脑博士天天这么折腾,早已熟练,溶液在倒的过程中不会有丢失。
写一个程序去帮助无脑博士找出当 AA 试管是空的时候,CC 试管中硫酸铜溶液所剩量的所有可能性。
输入格式
输入包括一行,为空格分隔开的三个数,分别为整数 A,B,CA,B,C。
输出格式
输出包括一行,升序地列出当 AA 试管是空的时候,CC 试管溶液所剩量的所有可能性。
样例输入:
2 5 10
样例输出:
5 6 7 8 9 10
参考代码如下:
#include <iostream>
#include<stdio.h>
#include<string.h>
#include<queue>
#include<stack>
using namespace std;
struct state
{
int a;
int b;
int c;
};
bool vis [21][21][21];
bool vis_c[21];
priority_queue<int>q;
state s;
int A,B,C;
int cnt=0;
void dfs()
{
// cout<<s.a<<" "<<s.b<<" "<<s.c<<endl;
vis[s.a][s.b][s.c]=1;
if(s.a==0)
{
if(!vis_c[s.c])
{
q.push(s.c);
vis_c[s.c]=1;cnt++;
}
}
int t;
if(s.a>0)
{
t=(s.b+s.a)<=B?s.a:B-s.b;//若a试管与b试管溶液的和不超过b试管容量,则倒光a中溶液,否则倒b试管剩余空间的体积(B-s.b),下同
if(t>s.a)t=s.a;
s.a-=t;s.b+=t;
if(!vis[s.a][s.b][s.c])dfs();
s.a+=t;s.b-=t;
t=(s.c+s.a)<=C?s.a:C-s.c;
if(t>s.a)t=s.a;
s.a-=t;s.c+=t;
if(!vis[s.a][s.b][s.c])dfs();
s.a+=t;s.c-=t;
}
if(s.b>0)
{
t=(s.b+s.a)<=A?s.b:A-s.a;
if(t>s.b)t=s.b;
s.b-=t;s.a+=t;
if(!vis[s.a][s.b][s.c])dfs();
s.b+=t;s.a-=t;
t=(s.b+s.c)<=C?s.b:C-s.c;
if(t>s.b)t=s.b;
s.b-=t;s.c+=t;
if(!vis[s.a][s.b][s.c])dfs();
s.b+=t;s.c-=t;
}
if(s.c>0)
{
t=(s.c+s.a)<=A?s.c:A-s.a;
if(t>s.c)t=s.c;
s.c-=t;s.a+=t;
if(!vis[s.a][s.b][s.c])dfs();
s.c+=t;s.a-=t;
t=(s.c+s.b)<=B?s.c:B-s.b;
if(t>s.c)t=s.c;
s.c-=t;s.b+=t;
if(!vis[s.a][s.b][s.c])dfs();
s.c+=t;s.b-=t;
}
}
int main()
{
// freopen("C://Users/tushuguan/Desktop/acm.txt","r",stdin);
cin>>A>>B>>C;
s.a=0;s.b=0;s.c=C;
memset(vis,sizeof(vis),false);
memset(vis_c,sizeof(vis_c),false);
dfs();
int c;
stack<int>sta;
while(!q.empty())
{
c=q.top();
q.pop();
sta.push(c);
}
while(!sta.empty())
{
c=sta.top();
sta.pop();
cout<<c;
if(!sta.empty())cout<<" ";
else cout<<endl;
}
// fclose(stdin);
return 0;
}