计蒜客 无脑博士和他的试管们
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了计蒜客 无脑博士和他的试管们相关的知识,希望对你有一定的参考价值。
无脑博士有三个容量分别是A,B,C升的试管,A,B,C分别是三个从1到20的整数,最初,A和B试管都是空的,而C试管是装满硫酸铜溶液的。有时,无脑博士把硫酸铜溶液从一个试管倒到另一个试管中,直到被灌试管装满或原试管空了。当然每一次灌注都是完全的。由于无脑博士天天这么折腾,早已熟练,溶液在倒的过程中不会有丢失。
写一个程序去帮助无脑博士找出当A是个是空的时候,C试管中硫酸铜溶液所剩量的所有可能性。
输入包括一行,为空格分隔开的三个数,分别为整数A,B和C。
输出包括一行,升序地列出当A试管是空的时候,C试管溶液所剩量的所有可能性。
样例1
输入:
2 5 10
输出:
5 6 7 8 9 10
- #include <stdio.h>
- #include <string.h>
- #define MAX 21
- int state[MAX][MAX],A,B,C;//状态数组state[i][j]代表A试管中有 i 升 溶液 B试管中有 j 升溶液的状态是否存在
- void dfs(int a,int b,int c){
- ?????state[a][b]=1;
- ?????if(a<A){//
- ??????????if(c>=A-a&&state[A][b]==0)dfs(A,b,c-A+a);//可倒满
- ??????????if(c<A-a&&state[a+c][b]==0)dfs(a+c,b,0);//从c倒入a,不可倒满,以下也是
- ??????????if(b>=A-a&&state[A][b-A+a]==0)dfs(A,b-A+a,c);
- ??????????if(b<A-a&&state[a+b][0]==0)dfs(a+b,0,c);//从b倒入a
- ??????}
- ??????if(b<B){
- ??????????if(c>=B-b&&state[a][B]==0)dfs(a,B,c-B+b);
- ??????????if(c<B-b&&state[a][b+c]==0)dfs(a,b+c,0);//从c倒入b
- ??????????if(a>=B-b&&state[a-B+b][B]==0)dfs(a-B+b,B,c);
- ??????????if(a<B-b&&state[0][a+b]==0)dfs(0,a+b,c);//从a倒入b
- ??????}
- ??????if(c<C){
- ??????????if(a>=C-c&&state[a-C+c][b]==0)dfs(a-C+c,b,C);
- ??????????if(a<C-c&&state[0][b]==0)dfs(0,b,c+a);//从a倒入c
- ??????????if(b>=C-c&&state[a][b-C+c]==0)dfs(a,b-C+c,C);
- ??????????if(b<C-c&&state[a][0]==0)dfs(a,0,b+c);从b倒入c
- ??????}
- }
- int main(){
- ???int i;
- ???scanf("%d%d%d",&A,&B,&C);
- ???memset(state,0,sizeof(state));
- ???dfs(0,0,C);
- ???int frist=1;//用于保证输出格式,首次输出不在数字前加空格
- ???for(i=B;i>=0;i--){
- ??????if(state[0][i]){//若存在A试管为0,B试管为 i的状态,则输出
- ?????????if(frist)frist=0;
- ?????????else printf(" ");
- ??????????????printf("%d",C-i);
- ?????????????}
- ??????}
- ????return 0;
- }
?
又是一道dp题目(和倒水问题很像)这次就是用到所谓记忆化搜索的方式进行动态规划,同时对解答图进行了dfs,练习dfs就是我做这题的本意。
因为总的溶液量为C 故 可用(i,j)来表示状态,i 为试管 A 当前容量 ,j 为 试管B 当前容量, 显然,C 试管容量为 C – i - j,从(i,j)状态可能发生的变化,即倒水的方式只有
c -> a ,b - > a, c - > b, a -> b, a -> c , b - >c 这6种方式。
而从 一个试管倒水到另一个试管有两种可能性,倒水试管和变为 0 和接水 试管被倒满 (我们可把倒水试管变为0且接水试管接满归到两种情况之一),
于是我们可通过两试管当前容量与最大容量的关系来判断某种倒水方式能否进行
同时,对于可能出现的重复状态,我们用数组state来进行记忆,标志某种状态是否出现过,来减少重复计算,同时可用state数组来得出最终解。又发现状态即为解的情况。。
最后又是吐槽时间,计蒜客的题目的分类让我总是能快速找到解题的方向,这道题想出思路花了我没多久时间,因为是递归的实现起来也不能,就是在if判断哪里码了好久,尼玛
一点错误都不能有,我只能小心翼翼地写,幸亏一次正确,但是这题我还是WA了,因为输出格式错误,我做过这么多题(并没有)还是第一次看到这种错误提示,从白书里看到
的技巧第一次有了用武之地,然后就AC了,这题还是蛮水的,但也挺典型的。还有下载的word代码高亮插件不给力啊。。为什么没有C/C++的啊!幸亏其他语言也有
int If //注释什么的,有了这些基本代码还能看,还有我真的无法对vim喜欢起来,特别是计蒜客那个在线阉割版的,我就是个只能靠IDE的普通人没办法。。
以上是关于计蒜客 无脑博士和他的试管们的主要内容,如果未能解决你的问题,请参考以下文章