藍橋杯第五屆題目求解
第四題
題目
- 今有7對數字:兩個1,兩個2,兩個3,…兩個7,把它們排成一行。
要求,兩個1間有1個其它數字,兩個2間有2個其它數字,以此類推,兩個7之間有7個其它數字。如下就是一個符合要求的排列:
17126425374635
當然,如果把它倒過來,也是符合要求的。
請你找出另一種符合要求的排列法,並且這個排列法是以74開頭的。
注意:只填寫這個14位的整數,不能填寫任何多餘的內容,比如說明註釋等。
程式碼
#include <iostream> #include <algorithm> #include <math.h> #include <string.h> #include <stdio.h> using namespace std; int res[14]; // 最終的排序結果 int t[7]; // 7個數的使用次數 void dfs( int x ) { if( x == 14 ) { for(int i=0;i<14;i++) printf("%d", res[i]); printf("\n"); return; } for(int i=0;i<7;i++) { if( t[i] <= 0 ) continue; if( t[i] == 2 ) { t[i]--; res[x] = i+1; dfs( x+1 ); t[i]++; } else if(t[i] == 1) { if( i+2<=x && i+1 == res[x-i-2] ) { t[i]--; res[x] = i+1; dfs( x+1 ); t[i]++; } } } } int main() { for(int i=0;i<7;i++) t[i] = 2; // 初始2次 res[0] = 7; res[1] = 4; t[3] = 1; t[6] = 1; dfs( 2 ); return 0; }
* 注:只用DFS求解即可。
第六題
題目
- 你一定聽說過“數獨”遊戲。
如【圖1.png】,玩家需要根據9×9盤面上的已知數字,推理出所有剩餘空格的數字,並滿足每一行、每一列、每一個同色九宮內的數字均含1-9,不重複。
數獨的答案都是唯一的,所以,多個解也稱為無解。
本圖的數字據說是芬蘭數學家花了3個月的時間設計出來的較難的題目。但對會使用計算機程式設計的你來說,恐怕易如反掌了。
本題的要求就是輸入數獨題目,程式輸出數獨的唯一解。我們保證所有已知資料的格式都是合法的,並且題目有唯一的解。
格式要求:
輸入9行,每行9個數字,0代表未知,其它數字為已知。
輸出9行,每行9個數字表示數獨的解。
程式碼
- 使用DFS就可以直接求解
src.txt中的內容是
005300000 800000020 070010500 400005300 010070006 003200080 060500009 004000030 000009700
-
#include <iostream> #include <algorithm> #include <math.h> #include <string.h> #include <stdio.h> using namespace std; int a[9][9]; // 判斷行與列是否為重複 bool noRepeatRowCol(int r, int c, int val) { for(int i=0;i<9;i++) if( a[i][c] == val ) return false; for(int i=0;i<9;i++) if( a[r][i] == val ) return false; return true; } // 判斷一個小的3X3方格中是否重複 bool noRepeatBox(int r, int c, int val) { int r1 = r/3, c1=c/3; for(int i=0;i<3;i++) { for(int j=0;j<3;j++) { if( a[r1*3+i][c1*3+j] == val ) return false; } } return true; } // 輸出九宮格的資訊 void print() { for(int i=0;i<9;i++) { for(int j=0;j<9;j++) cout << a[i][j]; cout << endl; } } void dfs(int r, int c) { if( r >= 9 ) { print(); return; } if( a[r][c] == 0 ) { for(int i=1;i<=9;i++) { if( noRepeatRowCol(r,c,i) && noRepeatBox(r,c,i) ) { a[r][c] = i; dfs( r+(c+1)/9, (c+1)%9 ); a[r][c] = 0; } } } else { dfs( r+(c+1)/9, (c+1)%9 ); } } int main() { char s[10][10]; FILE *fp = fopen("src.txt","r"); for(int i=0;i<9;i++) { fscanf(fp,"%s",&s[i]); } fclose( fp ); for(int i=0;i<9;i++) for(int j=0;j<9;j++) a[i][j] = s[i][j] - 48; dfs(0,0); return 0; }
第七題
題目
G將軍有一支訓練有素的軍隊,這個軍隊除開G將軍外,每名士兵都有一個直接上級(可能是其他士兵,也可能是G將軍)。現在G將軍將接受一個特別的任務,需要派遣一部分士兵(至少一個)組成一個敢死隊,為了增加敢死隊隊員的獨立性,要求如果一名士兵在敢死隊中,他的直接上級不能在敢死隊中。
請問,G將軍有多少種派出敢死隊的方法。注意,G將軍也可以作為一個士兵進入敢死隊。
輸入格式
輸入的第一行包含一個整數n,表示包括G將軍在內的軍隊的人數。軍隊的士兵從1至n編號,G將軍編號為1。
接下來n-1個數,分別表示編號為2, 3, …, n的士兵的直接上級編號,編號i的士兵的直接上級的編號小於i。
輸出格式
輸出一個整數,表示派出敢死隊的方案數。由於數目可能很大,你只需要輸出這個數除10007的餘數即可。
樣例輸入1
3
1 1
樣例輸出1
4
樣例說明
這四種方式分別是:
1. 選1;
2. 選2;
3. 選3;
4. 選2, 3。
樣例輸入2
7
1 1 2 2 3 3
樣例輸出2
40
資料規模與約定
對於20%的資料,n ≤ 20;
對於40%的資料,n ≤ 100;
對於100%的資料,1 ≤ n ≤ 100000。
資源約定:
峰值記憶體消耗 < 256M
CPU消耗 < 2000ms
請嚴格按要求輸出,不要畫蛇添足地列印類似:“請您輸入…” 的多餘內容。
所有程式碼放在同一個原始檔中,除錯通過後,拷貝提交該原始碼。
注意: main函式需要返回0
注意: 只使用ANSI C/ANSI C++ 標準,不要呼叫依賴於編譯環境或作業系統的特殊函式。
注意: 所有依賴的函式必須明確地在原始檔中 #include , 不能通過工程設定而省略常用標頭檔案。
提交時,注意選擇所期望的編譯器型別。
程式碼
#include <iostream>
#include <algorithm>
#include <math.h>
#include <string.h>
#include <stdio.h>
using namespace std;
int N;
// a[i]=n表示士兵i的上級為n
int a[100005];
// 標記位,判斷士兵i是否在當前的隊伍中
bool isin[100005];
int sum = 0;
bool tmp = false;
void dfs(int n)
{
if( n > N )
return;
tmp = true;
for(int i=1;i<n;i++)
{
if( isin[i] && (a[i]==n || a[n]==i) )
{
tmp = false;
break;
}
}
// 下標為n的士兵可以插入到當前敢死隊中,與之前的隊伍不衝突
if( tmp )
{
sum = (sum+1) % 10007;
isin[n] = true;
dfs( n+1 );
isin[n] = false;
}
// 不加入當前士兵是另一種方法
dfs( n+1 );
}
int main()
{
scanf("%d", &N);
for(int i=2;i<=N;i++)
scanf("%d", &a[i]);
a[1] = -1; // 將軍沒有上級
for(int i=1;i<N;i++)
isin[i] = false;
dfs( 1 );
cout << sum << endl;
return 0;
}