在九度刷題時,有一道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 }