USACO 1.4.5 Mother's Milk

来源:互联网 发布:程序员必看书籍 编辑:程序博客网 时间:2024/05/29 03:49

USACO   1.4.5 Mother's Milk

        2014.07.31、2014.08.02

        好久没有写博客了,回家了20几天,终于该做的事零零落落都慢慢整理好了,静下心开始敲敲代码,看看书。

USACO的第一章第四节的最后一道题,这一节都是关于搜索的题目,最重要的是看到一道抽象的问题,把问题总结成一个模型。也许之前的题目有些并没有按照题目希望总结出的模型去做。之后会翻一翻整理。

        题意:给出3个容量固定的罐子A,B,C,一开始的时候A,B罐都是空的,C罐是满的,然后从一个罐子往另外一个罐子倒牛奶(牛奶在欧美真是深入人心,这都milk3了),要么另外一个罐子已经被倒满了,要么这个罐子里已经没有牛奶了,问当A罐中没有牛奶的时候,C罐中的牛奶的量都有哪些数目的可能,答案要求排好序。

        好吧,总结出这是搜索题目,无所谓深搜广搜,因为所有可能的情况都必须搜索到,我的算深搜,一共有6种情况,分别为A->B,A->C,B->A,B->C,C->A,C->B,然后建立一个三维数组,分别以A、B、C三个罐中当前的牛奶量为坐标,用倒来倒去过程中可能出现的状况为这个数组中的点,然后就按照上面提到的6种情况的顺序进行搜索,并且用数组记录搜索过程中所有出现的情况。倒牛奶的每一步都有6种倒的方法,如果某种方法可行(就是数组中的这个点没有遇到过),就进入对下一步倒的方法的搜索,深搜,如果某种方法不可行(数组中这个点已经出现过,没有必要再从这个点搜索下去),就尝试其他方法,广搜,如果在这一步所有方法都不可行,说明上一步的方法不可行,退回去,对上一步广搜。

        网上可以搜到各种解题方法和分析。。

        细节+代码:   

/*      ID: 15257142      LANG: C      TASK: milk3  */#include<stdio.h>#include<string.h>int a,b,c,a1,b1,c1,num[30][30][30],rem[10];/*这个函数计算6种情况的具体每一种做完倒牛奶这一步后操作的2个罐中的牛奶量。*/void judge(int a1,int b1,int i){ //i是指哪个罐被倒入牛奶,if(a1>0&&b1<rem[i]){ //因为数组被函数操作的结果不消亡,但是数值会消亡。if(a1>=(rem[i]-b1)){ //a1,b1虽然是全局,但在这里只是函数的形参,况且a1,b1只能代表6种情况中的一种。a1 = a1-(rem[i]-b1); //rem数组记录了3个罐容量,用来计算比较。b1 = rem[i];}if(a1<(rem[i]-b1)){ //外层if是形参的两个罐可以a1倒给b1的条件。b1 = b1+a1; //内层是根据两个罐子现有的牛奶量,a1 = 0; //这样倒完之后两个罐剩余的奶量可能出现的情况。}}rem[0] = a1; rem[1] = b1; //rem数组记录参与倒这个过程的罐中当前的奶量。}/*这个函数是当搜索到不可行的方法的时候,将坐标退回到深搜的上一步。*/void back(int a2,int b2,int c2){a1 = a2;b1 = b2;c1 = c2;}/*这个函数是深广搜具体。关键。*/void dfs(){int a2,b2,c2; //这三个变量记录了当前深搜到的这一步3个罐中的牛奶量。a2  = a1;  b2 = b1;  c2 = c1; //必须写在函数里,而不是全局,if(a1>0&&b1<b){ //如果是全局,他们的值会随着深搜到的下一步而改变,judge(a1,b1,4); //写在函数里每一层的值会随着深搜到的某一步和在这一步的广搜的函数层结束而消亡,a1 = rem[0];  b1 = rem[1]; //退回到上一步的时候,坐标也可以跟着退回。if(num[a1][b1][c1]==1) //广搜不可行。当前坐标点不变。back(a2,b2,c2);if(num[a1][b1][c1]==0){ //这一步可行,记录状态,深搜。num[a1][b1][c1] = 1;dfs();back(a2,b2,c2); //深搜结束,坐标退回进入深搜的函数层的位置。}}if(a1>0&&c1<c){ //6块,6种方法。judge(a1,c1,5);a1 = rem[0];  c1 = rem[1];if(num[a1][b1][c1]==1)back(a2,b2,c2);if(num[a1][b1][c1]==0){num[a1][b1][c1] = 1;dfs();back(a2,b2,c2);}}if(b1>0&&a1<a){judge(b1,a1,3);b1 = rem[0];  a1 = rem[1];if(num[a1][b1][c1]==1)back(a2,b2,c2);if(num[a1][b1][c1]==0){num[a1][b1][c1] = 1;dfs();back(a2,b2,c2);}}if(b1>0&&c1<c){judge(b1,c1,5);b1 = rem[0];  c1 = rem[1];if(num[a1][b1][c1]==1)back(a2,b2,c2);if(num[a1][b1][c1]==0){num[a1][b1][c1] = 1;dfs();back(a2,b2,c2);}}if(c1>0&&a1<a){judge(c1,a1,3);c1 = rem[0];  a1 = rem[1];if(num[a1][b1][c1]==1)back(a2,b2,c2);if(num[a1][b1][c1]==0){num[a1][b1][c1] = 1;dfs();back(a2,b2,c2);}}if(c1>0&&b1<b){judge(c1,b1,4);c1 = rem[0];  b1 = rem[1];if(num[a1][b1][c1]==1)back(a2,b2,c2);if(num[a1][b1][c1]==0){num[a1][b1][c1] = 1;dfs();back(a2,b2,c2);}}}int main(){freopen("milk3.in","r",stdin);            freopen("milk3.out","w",stdout);int s[30],i,j,f;scanf("%d%d%d",&a,&b,&c); //罐容量。a1 = b1 = 0; //这3个变量指的是罐中的实际牛奶量。c1 = c;memset(num,0,sizeof(num));memset(s,0,sizeof(s));memset(rem,0,sizeof(rem));rem[3] = a;  rem[4] = b;  rem[5] = c; //把3个罐的容量放在固定位置。num[a1][b1][c1] = 1; //一开始存在的点。dfs();for(i = 0;i<=20;i++){for(j = 0;j<=20;j++){if(num[0][i][j]==1)s[j] = 1; //找出过程中得到的A维为0的所有点,记录C维此时的值。}}f = 0;for(i = 0;i<=20;i++){ //按顺序输出C维的值。if(s[i]==1){if(f==1)printf(" ");f = 1;printf("%d",i);}}printf("\n");return 0;fclose(stdout);  }

        遇到一个从没有遇到的情况,断点调试的时候,编译器给出Administrator privileges required for OLE RemoteProcedure Call debugging: this feature will not work……提示不能断点调试。呵呵,解决方法,记一笔。就是win7不兼容,右键编译器快捷方式图标以管理员身份运行就好。

        呵呵做题都变成 不带注释敲代码---->A掉----->补好注释写博客,呵呵呵。


0 0
原创粉丝点击