1. 程式人生 > >2016年第七屆藍橋杯省賽(C/C++ A組)

2016年第七屆藍橋杯省賽(C/C++ A組)

此處有目錄↑

基本都是暴力搜尋解決,最後兩道演算法題不會 - -

1.父親和兒子 (列舉)

父親年齡是兩位數,且比兒子大27歲,問有多少種可能的情況?(父親30歲,兒子3歲也符合題意)

直接列舉父親年齡即可

答案是:7

  1. #include <cstdio>
  2. usingnamespace std;  
  3. int main() {  
  4.     int ans=0;  
  5.     for(int i=1;i<=9;++i)  
  6.         for(int j=0;j<=9;++j)  
  7.             if(10*i+j-10*j-i==27)  
  8.                 ++ans;  
  9.     printf("%d\n",ans);  
  10. }  

2.生日蠟燭 (列舉)

一個人從某一歲開始每年生日都在蛋糕上插上與年齡數值相同的蠟燭,下載他總共插了236根蠟燭,問他從多少歲時開始插蠟燭?

直接從1歲開始列舉,找到答案就停止

不過這樣答案是:26,後來看到網上說236也可以,這估計是個坑點

  1. #include <cstdio>
  2. usingnamespace std;  
  3. int solve() {  
  4.     int sta=0,sum,cur;  
  5.     while
    (1) {  
  6.         sum=cur=sta;  
  7.         while(sum<236)  
  8.             sum+=++cur;  
  9.         if(sum==236)  
  10.             return sta;  
  11.         ++sta;  
  12.     }  
  13. }  
  14. int main() {  
  15.     printf("%d\n",solve());  
  16. }  


3.填格子 (DFS)

有一個含有10個格子的圖形,現用0~9填充,連續的數不能填充在相鄰的格子中(包括對角線相鄰),問有多少種填充方法?


dfs即可,注意剪枝,就能秒出

不過我認為每個數字只能填一次,算出來是:1580

  1. #include <cstdio>
  2. #include <algorithm>
  3. usingnamespace std;  
  4. int grid[7][7],ans;  
  5. bool vis[11];  
  6. constint dr[4]={0,-1,-1,-1};//當前格子的正左、左上、正右、右上
  7. constint dc[4]={-1,-1,0,1};  
  8. bool isAvailable(int r,int c,int n) {  
  9.     for(int i=0;i<4;++i)  
  10.         if(abs(grid[r][c]-grid[r+dr[i]][c+dc[i]])<=1)  
  11.             returnfalse;  
  12.     returntrue;  
  13. }  
  14. void dfs(int r,int c) {  
  15.     if(r==3&&c==4)  
  16.         ++ans;  
  17.     for(int i=0;i<=9;++i) {  
  18.         grid[r][c]=i;  
  19.         if(!vis[i]&&isAvailable(r,c,i)) {  
  20.             vis[i]=true;  
  21.             int rr=r,cc=c+1;  
  22.             if(cc>4) {  
  23.                 ++rr;  
  24.                 cc=1;  
  25.             }  
  26.             dfs(rr,cc);  
  27.             vis[i]=false;  
  28.         }  
  29.         grid[r][c]=-9;  
  30.     }  
  31. }  
  32. int main() {  
  33.     for(int i=0;i<7;++i) {  
  34.         for(int j=0;j<7;++j) {  
  35.             grid[i][j]=-9;  
  36.         }  
  37.         vis[i]=false;  
  38.     }  
  39.     vis[7]=vis[8]=vis[9]=false;  
  40.     ans=0;  
  41.     dfs(1,2);  
  42.     printf("%d\n",ans);  
  43. }  

4.快速排序

資料結構學過,這麼快又忘了,還看了半天...

swap(a,p,j);

5.去掉尾1

如果一個數二進位制表示時,若個位是1,則去掉從個位起開始的連續的1,若個位不是1,則不變

答案是:x&(x+1)

很簡單的答案,可是當時一點都沒想到,自己想的是用3元運算子,連續巢狀31次實現這個功能,由於每次程式碼都一樣,所以用迴圈生成程式碼,最後交了700多B...

6.四則運算 (DFS)

有1~13共13個數,將12個不同的數填入下列12個空使四個運算都成立,問有多少種方法?


依舊是dfs+剪枝就能秒出,答案是:64,感覺當時寫的不是64,估計當時拷程式碼時有地方沒改 :(

  1. #include <cstdio>
  2. usingnamespace std;  
  3. int a[15],ans;  
  4. bool vis[15];  
  5. void dfs(int dep) {  
  6.     if(dep==3) {  
  7.         if(a[1]/a[2]*a[2]==a[1]&&a[1]/a[2]>0&&!vis[a[1]/a[2]]) {  
  8.             vis[a[1]/a[2]]=true;  
  9.             dfs(4);  
  10.             vis[a[1]/a[2]]=false;  
  11.         }  
  12.         return ;  
  13.     }  
  14.     if(dep==6) {  
  15.         if(a[4]*a[5]<=13&&!vis[a[4]*a[5]]) {  
  16.             vis[a[4]*a[5]]=true;  
  17.             dfs(7);  
  18.             vis[a[4]*a[5]]=false;  
  19.         }  
  20.         return ;  
  21.     }  
  22.     if(dep==9) {  
  23.         if(a[7]+a[8]<=13&&!vis[a[7]+a[8]]) {  
  24.             vis[a[7]+a[8]]=true;  
  25.             dfs(10);  
  26.             vis[a[7]+a[8]]=false;  
  27.         }  
  28.         return ;  
  29.     }  
  30.     if(dep==12) {  
  31.         if(a[10]+a[11]<=13&&!vis[a[10]+a[11]])  
  32.             ++ans;  
  33.         return ;  
  34.     }  
  35.     for(int i=1;i<=13;++i) {  
  36.         if(!vis[i]) {  
  37.             vis[i]=true;  
  38.