演算法學習——回溯之伯努利裝錯信封問題
阿新 • • 發佈:2018-11-06
演算法描述
某人給6個朋友每個人都寫了一封信,同時寫了這6個朋友地址的信封,有多少種投放信箋的方法,使得每封信與信封上的收信人都不相符?
演算法思路
- 6封信可能出現的結果:
所有的信都是在對應的信封中,也就是所有的信都放對了信封,這種情況只有一種
部分信放錯了信封
全部信都放錯了信封
題目要求的就是求最後一種情況,也就是全部新都放錯了信封
定義一個數組
a[i]
,a[1] = 1
表示第一封信放在了第一個信封中- 限制條件
a[i]!=i
即限制信放在正確的信封中a[i]!=a[j]
即限制信不能放在同一個信封
回溯條件
a[i]=6
即已經遍歷到了最後一封信
演算法實現
System.out.println("輸入n:"); Scanner scaner = new Scanner(System.in); int n = scaner.nextInt(); scaner.close(); int s = 0;//解的個數統計 int[] a = new int[n+1]; a[1]=2; int i=1; while(true){ boolean flag = true; if(a[i]!=i){ for(int j=1;j<i;j++){ if(a[j]==a[i]){ flag = false; break; } } }else{ flag = false; } if(flag&&i==n){ s++; for(int j=1;j<=n;j++){ System.out.print(a[j]); } System.out.print(" "); //出現十個解換行 if(s%10==0){ System.out.println(""); } } if(flag&&i<n){ i++; a[i]=1; continue; } while(a[i]==n&&i>0){ i--;//回溯,a[i]到末尾,則回溯 } if(i>0){ a[i]++;//向後移 }else{ break; } } System.out.println("\n"+"s="+s);