在九度刷题时,有一道1036的Old Bill,http://ac.jobdu.com/problem.php?pid=1036。里面涉及了双重循环。
由于九度的样例从来就不是一组一组的,有很多组,所以从1000题的a+b起,编程时都会习惯性地加上一句while(scanf("%d%d",&a,&b)!=EOF)
本题是while(scanf("%d%d%d%d",&N,&x,&y,&z)!=EOF&&N>0&&N<100)
然后本题又有一个双重循环,所以实质上是:如何从三重循环里跳出两重,留在最外面一重。
通常退出双重循环的方法有以下几种。
1、用GOTO。
虽然这几乎能破所有从n重循环中跳到第m重(m<=n)的问题,但是GOTO语言会破坏程序结构,不是万不得已的情况下,就别用了。
A:这么好的东西不用?那我没别的办法了,╮(╯▽╰)╭。你给我个方法?
甚至,在这篇文章里http://zhidao.baidu.com/question/54376881.html,我还发现java对于这个问题,还有带标号的break和continue(java你考虑得太多了)。
原文解释部分:
break和continue都可以有一个可选择的标号,它用来告诉Java从哪里开始继续执行程序。没有标号的时候,break在嵌套循环中会跳出最近的循环,进入到包含这层循环的外层循环中,或者在单层循环中跳到循环外的下一条语句上。而continue重新进行它所在层次的循环。使用带标号的break 和continue后,你可以用break进入到嵌套循环外的某个位置,或用continue来进入当前循环的外层循环中。
要使用标号的循环,在循环的开始部分前面加标号,在标号和循环之间带有一个冒号。然后当你使用break 或continue时,在它们后面加上标号的名字。
原文代码部分:
out: for (int I=0;I<10;I++) {
while (x<50)
{ if (I*x++>400) break out; //inner loop here } //outer loop here }
2、用return。
这个够干脆,直接跳出函数,但我后面还要处理一些细节这么办?
A:不要在意这些细节(Don't mind)。
3、用flag变量(双break1)。
在每层循环中设置一个变量,一般是flag,多重的话就可以是flag1,flag2,flag3……或者你对英文标号的顺序很熟悉的话,就用a,b,c,d……吧。
先初始化flag的值可以是0(也可以是1,whatever)
在内层循环中,要跳出时,把flag改变,外层循环加个判断,看看flag是否改变,改变了,我也退,双break,那就退出了双重循环。
举个例子吧:
C/C++ http://bbs.csdn.net/topics/390283756
int flag=0; for(b1=y2;b1<y2+4;b1++) { for(a1=x2;a1<x2+4;a1++) { if(state[b1][a1]==0) { flag=1; break; } else sumpr1+=state[b1][a1]; } if(flag==1) break; }
C# http://zhidao.baidu.com/question/280303094.html
外循环内内循环外加一个bool bool exitLoop = false; 在内循环要退出的时候设置一下 exitLoop = true; 然后外循环里面,if(exitLoop) break; 即可
Java http://www.myexception.cn/program/663151.html
int arr[][] = {{1,2,3},{4,5,6,7},{9}}; boolean found = false; for(int i=0;i<arr.length && !found;i++) { for(int j=0;j<arr[i].length;j++) { System.out.println(“i=” + i + “,j=” + j); if(arr[i][j] == 5) { found = true; break; } } }
4、判断是否自然跳出(双break2)。
其实flag变量法,就是内外层循环的互动,不过CSDN上高手在这个互动上又有更高级一点的想法。
前面是你内层主动改变flag变量,出异常。要是你flag不变,甚至没有flag,怎么办?
难不倒我们的刑侦专家,我外层检测你内层的跳出条件是否达到,是否自然跳出,不是自然跳出就是异常break嘛,你跳出,我也跳(You jump,I jump),双break一起跳出双重循环。是不是和我们最开始学质数判断时,flag法或i>=n/2法很像。
举个例子:还是刚才CSDN那个帖子http://bbs.csdn.net/topics/390283756
for(b1=y2;b1<y2+4;b1++) { for(a1=x2;a1<x2+4;a1++) { if(state[b1][a1]==0) break; else sumpr1+=state[b1][a1]; } if(a1<x2+4) break; }
5、将跳出条件变量设置溢出(特别推荐)
刚说外层是刑侦专家,就来了个无间道,真是道高一尺魔高一丈啊!
把你要跳出的那层循环的跳出条件变量设置溢出,不要跳出的就不设置。话说你也可以任意设置,那这方法就和GOTO一样坑爹了,所以你还是规矩地就设置那些你要跳出的那些层循环的跳出条件变量,最好就设置成临界值。
有些绕,看看例子就简介明了了:http://hi.baidu.com/sharlanori/item/164961841813211cc316270d
for(int i = 0;i < 10;++i) { for(int j = 0;j < 100;++j) { if(condition) { i = 10; j = 100;//让循环终止条件为真,这样就跳出双重循环了 } ...... } } //在实际使用的时候可以根据实际情况来设置这个循环终止条件。
绕回来吧,我的1036题就是用这个方法做的,感谢aleczhou。
下面上我1036的AC代码。
1 #include<stdio.h> 2 int main(void) 3 { 4 int N,x,y,z; 5 int i,j,t; 6 while(scanf("%d%d%d%d",&N,&x,&y,&z)!=EOF&&N>0&&N<100) 7 { 8 int k=0; 9 for(i=9;i>=1;i--) 10 { 11 for(j=9;j>=0;j--) 12 { 13 t=i*10000+x*1000+y*100+z*10+j; 14 if(0==t%N) 15 { 16 k=t/N; 17 j=0;i=1; 18 } 19 } 20 } 21 if(k==0) 22 printf("0\n"); 23 else 24 printf("%d %d %d\n",k*N/10000,(k*N)%10,k); 25 } 26 return 0; 27 }