1. 程式人生 > >2014年第五屆藍橋杯B組(C/C++)預賽題目及個人答案(歡迎指正)

2014年第五屆藍橋杯B組(C/C++)預賽題目及個人答案(歡迎指正)

1.標題:啤酒和飲料


    啤酒每罐2.3元,飲料每罐1.9元。小明買了若干啤酒和飲料,一共花了82.3元。


    我們還知道他買的啤酒比飲料的數量少,請你計算他買了幾罐啤酒。


    注意:答案是一個整數。請通過瀏覽器提交答案。


    不要書寫任何多餘的內容(例如:寫了飲料的數量,新增說明文字等)。

一開始用直接用題目中的帶有小數點的資料執行不出來,上下乘以10以後再計算就出來了,所以說,在藍橋杯比賽中對於這種只需要填出最終結果的小題,能用整形就用整形,避免浮點型的數以防出錯。

#include<stdio.h>
int main()
{
    for(int i=0; i<=823/23; i++)
        for(int j=i+1; j<=(823-23*i)/19; j++)
            if(23*i+19*j==823)
                printf("%d\n",i);
    return 0;
}

執行結果:11

2.標題:切面條


    一根高筋拉麵,中間切一刀,可以得到2根麵條。


    如果先對摺1次,中間切一刀,可以得到3根麵條。


    如果連續對摺2次,中間切一刀,可以得到5根麵條。


    那麼,連續對摺10次,中間切一刀,會得到多少麵條呢?


答案是個整數,請通過瀏覽器提交答案。不要填寫任何多餘的內容。

自己模擬剪幾下,找出規律。

#include<stdio.h>
int main()
{
    int ans=2;
    for(int i=1; i<=10; i++)
        ans=ans*2-1;
    printf("%d\n",ans);
    return 0;
}

執行結果:1025

3.標題:李白打酒


    話說大詩人李白,一生好飲。幸好他從不開車。


    一天,他提著酒壺,從家裡出來,酒壺中有酒2鬥。他邊走邊唱:


    無事街上走,提壺去打酒。
    逢店加一倍,遇花喝一斗。


    這一路上,他一共遇到店5次,遇到花10次,已知最後一次遇到的是花,他正好把酒喝光了。 


    請你計算李白遇到店和花的次序,可以把遇店記為a,遇花記為b。則:babaabbabbabbbb 就是合理的次序。像這樣的答案一共有多少呢?請你計算出所有可能方案的個數(包含題目給出的)。


    注意:通過瀏覽器提交答案。答案是個整數。不要書寫任何多餘的內容。

DFS,注意判斷條件,以及搜尋方法。

#include<stdio.h>
int ans=0;
char s[15];
void dfs(int a,int b,int jiu,int sum)
{

    if(!jiu&&!a&&!b&&s[14]=='b')//尤其注意這裡的條件設定:酒喝光了,遇到了5個店,10朵花,最後遇到的是花。
    {
        ans++;
        return ;
    }
    if(a>0)
    {
        s[sum]='a';
        dfs(a-1,b,jiu*2,sum+1);
    }
    if(b>0&&jiu>0)
    {
        s[sum]='b';
        dfs(a,b-1,jiu-1,sum+1);
    }
}
int main()
{
    int jiu=2;
    dfs(5,10,jiu,0);
    printf("%d\n",ans);
    return 0;
}
執行結果:14

4.標題:史豐收速算


    史豐收速演算法的革命性貢獻是:從高位算起,預測進位。不需要九九表,徹底顛覆了傳統手算!


    速算的核心基礎是:1位數乘以多位數的乘法。


    其中,乘以7是最複雜的,就以它為例。


    因為,1/7 是個迴圈小數:0.142857...,如果多位數超過 142857...,就要進1


    同理,2/7, 3/7, ... 6/7 也都是類似的迴圈小數,多位數超過 n/7,就要進n


    下面的程式模擬了史豐收速演算法中乘以7的運算過程。


    乘以 7 的個位規律是:偶數乘以2,奇數乘以2再加5,都只取個位。


    乘以 7 的進位規律是:
滿 142857... 進1,
滿 285714... 進2,
滿 428571... 進3,
滿 571428... 進4,
滿 714285... 進5,
滿 857142... 進6


    請分析程式流程,填寫劃線部分缺少的程式碼。




//計算個位 
int ge_wei(int a)
{
if(a % 2 == 0)
return (a * 2) % 10;
else
return (a * 2 + 5) % 10;
}


//計算進位 
int jin_wei(char* p)
{
char* level[] = {
"142857",
"285714",
"428571",
"571428",
"714285",
"857142"
};

char buf[7];
buf[6] = '\0';
strncpy(buf,p,6);

int i;
for(i=5; i>=0; i--){
int r = strcmp(level[i], buf);
if(r<0) return i+1;
while(r==0){
p += 6;
strncpy(buf,p,6);
r = strcmp(level[i], buf);
if(r<0) return i+1;
______________________________;  //填空
}
}

return 0;
}


//多位數乘以7
void f(char* s) 
{
int head = jin_wei(s);
if(head > 0) printf("%d", head);

char* p = s;
while(*p){
int a = (*p-'0');
int x = (ge_wei(a) + jin_wei(p+1)) % 10;
printf("%d",x);
p++;
}

printf("\n");
}


int main()
{
f("428571428571");
f("34553834937543");
return 0;
}




注意:通過瀏覽器提交答案。只填寫缺少的內容,不要填寫任何多餘的內容(例如:說明性文字)

答案:if(r>0) return i;

5.標題:列印圖形


    小明在X星球的城堡中發現瞭如下圖形和文字:
rank=3
   * 
  * * 
 *   *  
* * * *


rank=5
               *                                                      
              * *                                                     
             *   *                                                    
            * * * *                                                   
           *       *                                                  
          * *     * *                                                 
         *   *   *   *                                                
        * * * * * * * *                                               
       *               *                                              
      * *             * *                                             
     *   *           *   *                                            
    * * * *         * * * *                                           
   *       *       *       *  
  * *     * *     * *     * *  
 *   *   *   *   *   *   *   * 
* * * * * * * * * * * * * * * *  


ran=6
                               *                                      
                              * *                                     
                             *   *                                    
                            * * * *                                   
                           *       *                                  
                          * *     * *                                 
                         *   *   *   *                                
                        * * * * * * * *                               
                       *               *                              
                      * *             * *                             
                     *   *           *   *                            
                    * * * *         * * * *                           
                   *       *       *       *                          
                  * *     * *     * *     * *                         
                 *   *   *   *   *   *   *   *                        
                * * * * * * * * * * * * * * * *                       
               *                               *                      
              * *                             * *                     
             *   *                           *   *                    
            * * * *                         * * * *                   
           *       *                       *       *                  
          * *     * *                     * *     * *                 
         *   *   *   *                   *   *   *   *                
        * * * * * * * *                 * * * * * * * *               
       *               *               *               *              
      * *             * *             * *             * *             
     *   *           *   *           *   *           *   *            
    * * * *         * * * *         * * * *         * * * *           
   *       *       *       *       *       *       *       *          
  * *     * *     * *     * *     * *     * *     * *     * *         
 *   *   *   *   *   *   *   *   *   *   *   *   *   *   *   *        
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *       
                                                                      


    小明開動腦筋,編寫了如下的程式,實現該圖形的列印。


#define N 70


void f(char a[][N], int rank, int row, int col)
{
if(rank==1){
a[row][col] = '*';
return;
}

int w = 1;
int i;
for(i=0; i<rank-1; i++) w *= 2;

____________________________________________;
f(a, rank-1, row+w/2, col);
f(a, rank-1, row+w/2, col+w);
}


int main()
{
char a[N][N];
int i,j;
for(i=0;i<N;i++)
for(j=0;j<N;j++) a[i][j] = ' ';

f(a,6,0,0);

for(i=0; i<N; i++){
for(j=0; j<N; j++) printf("%c",a[i][j]);
printf("\n");
}

return 0;
}




    請仔細分析程式邏輯,填寫缺失程式碼部分。

首先觀察一下空格周圍的式子特徵,初步判定也是類似f(a, rank-1, row+w/2, col);f(a, rank-1, row+w/2, col+w);這樣的式子。根據遞迴的規律,在f()裡前兩個一定是a和rank-1,後面兩個基本就是靠試了,然後執行程式直到得出正確的圖形。

答案:    f(a,rank-1,row, col + w/2) ;

6.標題:奇怪的分式


    上小學的時候,小明經常自己發明新演算法。一次,老師出的題目是:


    1/4 乘以 8/5 


    小明居然把分子拼接在一起,分母拼接在一起,答案是:18/45 (參見圖1.png)


    老師剛想批評他,轉念一想,這個答案湊巧也對啊,真是見鬼!


    對於分子、分母都是 1~9 中的一位數的情況,還有哪些算式可以這樣計算呢?


    請寫出所有不同算式的個數(包括題中舉例的)。


    顯然,交換分子分母后,例如:4/1 乘以 5/8 是滿足要求的,這算做不同的算式。


    但對於分子分母相同的情況,2/2 乘以 3/3 這樣的型別太多了,不在計數之列!


注意:答案是個整數(考慮對稱性,肯定是偶數)。請通過瀏覽器提交。不要書寫多餘的內容。


直接暴力解題,同時注意題目中要求"對於分子分母相同的情況,不在計數之列!",因此這種情況要排除。

#include<stdio.h>
int main()
{
    double x,y,z,k;
    int ans=0;
    for(x=1.0; x<=9.0; x++)
        for(y=1.0; y<=9.0; y++)
            for(z=1.0; z<=9.0; z++)
                for(k=1.0; k<=9.0; k++)
                {
                    if(x==y&&z==k)
                        continue;
                    if((x*z)/(y*k)==(10*x+z)/(10*y+k))
                        ans++;
                }
    printf("%d\n",ans);
    return 0;
}

執行結果:14

7.標題:六角填數


    如圖【1.png】所示六角形中,填入1~12的數字。


    使得每條直線上的數字之和都相同。


    圖中,已經替你填好了3個數字,請你計算星號位置所代表的數字是多少?


請通過瀏覽器提交答案,不要填寫多餘的內容。


暴力解題,按照圖示的變數命名來


然而有時候暴力這樣簡單粗暴的方法也不是次次都用得好的,比如我的第一份程式碼就進行了19.827s 才能得出結果

第一份程式碼如下:

<pre name="code" class="cpp"><pre name="code" class="cpp">#include<stdio.h>
int main()
{
    int a1,a2,a3,a4,a5,a6,a7,a8,ans,flag=0;
    for(a1=1; a1<13; a1++)
    {
        for(a2=1; a2<13; a2++)
        {
            for(a3=1; a3<13; a3++)
            {
                for(a4=1; a4<13; a4++)
                {
                    for(a5=1; a5<13; a5++)
                    {
                        for(a6=1; a6<13; a6++)
                        {
                            for(a7=1; a7<13; a7++)
                            {
                                for(a8=1; a8<13; a8++)
                                {
                                    for(ans=1; ans<13; ans++)
                                    {
                                        if(a1==1||a1==3||a1==8||a2==1||a2==3||a2==8||a3==1||a3==3||a3==8||a4==1||a4==3||a4==8||a5==1||a5==3||a5==8||a6==1||a6==3||a6==8||a7==1||a7==3||a7==8||a8==1||a8==3||a8==8||ans==1||ans==3||ans==8)
                                            continue;
                                        if(a1!=a2&&a1!=a3&&a1!=a4&&a1!=a5&&a1!=a6&&a1!=a7&&a1!=a8&&a1!=ans&&a2!=a3&&a2!=a4&&a2!=a5&&a2!=a6&&a2!=a7&&a2!=a8&&a2!=ans&&a3!=a4&&a3!=a5&&a3!=a6&&a3!=a7&&a3!=a8&&a3!=ans&&a4!=a5&&a4!=a6&&a4!=a7&&a4!=a8&&a4!=ans&&a5!=a6&&a5!=a7&&a5!=a8&&a5!=ans&&a6!=a7&&a6!=a8&&a6!=ans&&a7!=a8&&a7!=ans&&a8!=ans)
                                        {
                                            int t1,t2,t3,t4,t5,t6;
                                            t1=1+a2+a4+a8;
                                            t2=1+a1+a5+ans;
                                            t3=a5+a6+a7+a8;
                                            t4=8+a1+a2+a3;
                                            t5=8+a6+ans+3;
                                            t6=3+a3+a4+a7;
                                            if(t1==t2&&t2==t3&&t3==t4&&t4==t5&&t5==t6)
                                            {
                                                printf("%d\n",ans);
                                                flag=1;
                                                break;
                                            }
                                        }
                                    }
                                    if(flag)
                                        break;
                                }
                                if(flag)
                                    break;
                            }
                            if(flag)
                                break;
                        }
                        if(flag)
                            break;
                    }
                    if(flag)
                        break;
                }
                if(flag)
                    break;
            }
            if(flag)
                break;
        }
    }
    return 0;
}


執行結果:10

實際上,暴力也是需要技巧滴~比如第二份程式碼就能縮短執行時間,只花了0.889s:

#include<stdio.h>
int main()
{
    int a1,a2,a3,a4,a5,a6,a7,a8,ans;
    for(a1=1; a1<13; a1++)
    {
        if(a1==1||a1==8||a1==3)
            continue;
        for(a2=1; a2<13; a2++)
        {
            if(a2==1||a2==8||a2==3||a2==a1)
                continue;
            for(a3=1; a3<13; a3++)
            {
                if(a3==1||a3==8||a3==3||a3==a1||a3==a2)
                    continue;
                for(a4=1; a4<13; a4++)
                {
                    if(a4==1||a4==8||a4==3||a4==a1||a4==a2||a4==a3)
                        continue;
                    for(a5=1; a5<13; a5++)
                    {
                        if(a5==1||a5==8||a5==3||a5==a1||a5==a2||a5==a3||a5==a4)
                            continue;
                        for(a6=1; a6<13; a6++)
                        {
                            if(a6==1||a6==8||a6==3||a6==a1||a6==a2||a6==a3||a6==a4||a6==a5)
                                continue;
                            for(a7=1; a7<13; a7++)
                            {
                                if(a7==1||a7==8||a7==3||a7==a1||a7==a2||a7==a3||a7==a4||a7==a5||a7==a6)
                                    continue;
                                for(a8=1; a8<13; a8++)
                                {
                                    if(a8==1||a8==8||a8==3||a8==a1||a8==a2||a8==a3||a8==a4||a8==a5||a8==a6||a8==a7)
                                        continue;
                                    for(ans=1; ans<13; ans++)
                                    {
                                        if(ans==1||ans==8||ans==3||ans==a1||ans==a2||ans==a3||ans==a4||ans==a5||ans==a6||ans==a7||ans==a8)
                                            continue;
                                        int t1,t2,t3,t4,t5,t6;
                                        t1=1+a2+a4+a8;
                                        t2=1+a1+a5+ans;
                                        t3=a5+a6+a7+a8;
                                        t4=8+a1+a2+a3;
                                        t5=8+a6+ans+3;
                                        t6=3+a3+a4+a7;
                                        if(t1==t2&&t2==t3&&t3==t4&&t4==t5&&t5==t6)
                                            printf("%d\n",ans);

                                    }
                                }
                            }
                        }
                    }
                }
            }
        }
    }

    return 0;
}

執行結果:10

第二份程式碼的好處在於減少判斷量,比如在判斷9個變數互不相等的時候不必再有8!個不等式需要判斷,只要保證當前for迴圈中的變數與之前的數不等即可。在判斷六條邊數字和相等時,不用寫出5!個等式來判斷,只需相鄰兩個和相等即可。

當然,暴力還是太麻煩了,運用DFS搜尋演算法方便快捷。第三份程式碼如下:

<span style="font-size:14px;">#include <cstdio>
#include<string.h>
int num[9]= {2,4,5,6,7,9,10,11,12};//還剩下這九個數
int vis[9];
int a[10];
bool judge()//判斷是否滿足六邊相等的條件
{
    int t1,t2,t3,t4,t5,t6;
    t1=1+a[2]+a[4]+a[8];
    t2=1+a[1]+a[5]+a[9];
    t3=a[5]+a[6]+a[7]+a[8];
    t4=8+a[1]+a[2]+a[3];
    t5=8+a[6]+a[9]+3;
    t6=3+a[3]+a[4]+a[7];
    if(t1==t2&&t2==t3&&t3==t4&&t4==t5&&t5==t6)
    {
        printf("%d\n",a[9]);
        return 1;
    }
    return 0;
}
void dfs(int n)
{
    if(n==10&&judge())//搜尋成功的條件是九個變數均擁有了互不相同的值,且滿足六條邊和相等的條件
        return ;
    for(int i=0; i<9; i++)
        if(!vis[i])//如果num[i]還沒有被賦給哪個變數過
        {
            a[n]=num[i];//就賦給a[n]
            vis[i]=1;//標記為"已用"
            dfs(n+1);//繼續搜尋下一個數
            vis[i]=0;//標記清零,以便搜尋失敗後再做嘗試
        }
}
int main()
{
    memset(vis,0,sizeof(vis));//標記陣列清零
    dfs(1);//從a[1]開始搜尋
    return 0;
}</span><span style="color: rgb(255, 0, 0); font-size: 18px;">
</span>

執行結果:10

8.標題:螞蟻感冒


    長100釐米的細長直杆子上有n只螞蟻。它們的頭有的朝左,有的朝右。 


    每隻螞蟻都只能沿著杆子向前爬,速度是1釐米/秒。


    當兩隻螞蟻碰面時,它們會同時掉頭往相反的方向爬行。


    這些螞蟻中,有1只螞蟻感冒了。並且在和其它螞蟻碰面時,會把感冒傳染給碰到的螞蟻。


    請你計算,當所有螞蟻都爬離杆子時,有多少隻螞蟻患上了感冒。




【資料格式】


    第一行輸入一個整數n (1 < n < 50), 表示螞蟻的總數。


    接著的一行是n個用空格分開的整數 Xi (-100 < Xi < 100), Xi的絕對值,表示螞蟻離開杆子左邊端點的距離。正值表示頭朝右,負值表示頭朝左,資料中不會出現0值,也不會出現兩隻螞蟻佔用同一位置。其中,第一個資料代表的螞蟻感冒了。


    要求輸出1個整數,表示最後感冒螞蟻的數目。


例如,輸入:
3
5 -2 8
程式應輸出:
1


再例如,輸入:
5
-10 8 -20 12 25
程式應輸出:
3


資源約定:
峰值記憶體消耗 < 256M
CPU消耗  < 1000ms




請嚴格按要求輸出,不要畫蛇添足地列印類似:“請您輸入...” 的多餘內容。


所有程式碼放在同一個原始檔中,除錯通過後,拷貝提交該原始碼。


注意: main函式需要返回0
注意: 只使用ANSI C/ANSI C++ 標準,不要呼叫依賴於編譯環境或作業系統的特殊函式。
注意: 所有依賴的函式必須明確地在原始檔中 #include <xxx>, 不能通過工程設定而省略常用標頭檔案。


提交時,注意選擇所期望的編譯器型別。

這個題乍一看腦袋裡好像很亂,其實理清頭緒後再敲出來就很容易了。首先一定要記住螞蟻都具有相同的速度,所以他們的相對位置不會變!   我們可以從第一隻那隻感冒的螞蟻入手,實際上,如果第一隻螞蟻向右爬,則它出發的位置右邊的螞蟻中向左爬且離第一隻螞蟻最近的那隻會被傳染,然後雙方會掉頭爬行,接下來,第一隻螞蟻左邊的螞蟻中向右爬行且離第一隻螞蟻最近的那隻會被傳染,雙方再掉頭。而對於一開始第一隻被傳染的那隻螞蟻來說,它會傳染給他右邊向左爬且最近的螞蟻……   所以,將問題簡化,實際上就是向右爬的第一隻感冒螞蟻會先傳染它右邊所有向左爬的螞蟻,掉頭向左爬時會傳染給左邊所有向右爬的螞蟻。   同理,若第一隻螞蟻開始時是向左爬,被傳染的螞蟻=左邊所有向右爬的螞蟻+右邊所有向左爬的螞蟻。   注意這種思想需要有個第一隻感冒的螞蟻是否會掉頭的判斷,因為第一隻螞蟻向左(或右)爬的時候,若不會遇到一隻迎面而來的螞蟻使它掉頭的話,則即使右邊有向左爬的螞蟻,也不會被其傳染。
#include<stdio.h>  
#include<string.h>  
struct Node  
{  
    int pos,dir;  
} Node[55];  
int main()  
{  
    int n,ans=1;  
    scanf("%d",&n);  
    memset(Node,0,sizeof(Node));  
    for(int i=0; i<n; i++)  
    {  
        scanf("%d",&Node[i].pos);  
        if(Node[i].pos>0)  
        {  
            Node[i].dir=1;  
        }  
        else  
        {  
            Node[i].dir=-1;  
            Node[i].pos*=-1;//注意正負僅僅表示方向,位置是其絕對值  
        }  
    }  
    int turn=0;//考慮到第一隻感冒的螞蟻可能不會掉頭的情況,設定標記turn,初始化為0  
    if(Node[0].dir==1)  
    {  
        for(int i=1; i<n; i++)  
        {  
            if((Node[i].pos>Node[0].pos)&&(Node[i].dir==-1))  
            {  
                turn=1;//第一隻感冒的螞蟻遇到迎面而來的螞蟻,它將掉頭,將turn標記為1  
                ans++;  
            }  
        }  
        for(int i=1; i<n; i++)  
        {  
            if((Node[i].pos<Node[0].pos)&&(Node[i].dir==1)&&turn)//只有第一隻螞蟻掉頭了,才會與另一方向前進的螞蟻出現碰頭的情形,因此注意加上turn是否為1的判斷  
                ans++;  
        }  
    }  
    else  
    {  
        for(int i=1; i<n; i++)  
        {  
            if((Node[i].pos<Node[0].pos)&&(Node[i].dir==1))  
            {  
                turn=1;  
                ans++;  
            }  
        }  
        for(int i=1; i<n; i++)  
        {  
            if((Node[i].pos>Node[0].pos)&&(Node[i].dir==-1)&&turn)  
                ans++;  
        }  
    }  
    printf("%d\n",ans);  
    return 0;  
}  


9.標題:地宮取寶



    X 國王有一個地宮寶庫。是 n x m 個格子的矩陣。每個格子放一件寶貝。每個寶貝貼著價值標籤。


    地宮的入口在左上角,出口在右下角。


    小明被帶到地宮的入口,國王要求他只能向右或向下行走。


    走過某個格子時,如果那個格子中的寶貝價值比小明手中任意寶貝價值都大,小明就可以拿起它(當然,也可以不拿)。


    當小明走到出口時,如果他手中的寶貝恰好是k件,則這些寶貝就可以送給小明。


    請你幫小明算一算,在給定的局面下,他有多少種不同的行動方案能獲得這k件寶貝。


【資料格式】


    輸入一行3個整數,用空格分開:n m k (1<=n,m<=50, 1<=k<=12)


    接下來有 n 行資料,每行有 m 個整數 Ci (0<=Ci<=12)代表這個格子上的寶物的價值


    要求輸出一個整數,表示正好取k個寶貝的行動方案數。該數字可能很大,輸出它對 1000000007 取模的結果。


例如,輸入:
2 2 2
1 2
2 1
程式應該輸出:
2


再例如,輸入:
2 3 2
1 2 3
2 1 5
程式應該輸出:
14




資源約定:
峰值記憶體消耗 < 256M
CPU消耗  < 1000ms




請嚴格按要求輸出,不要畫蛇添足地列印類似:“請您輸入...” 的多餘內容。


所有程式碼放在同一個原始檔中,除錯通過後,拷貝提交該原始碼。


注意: main函式需要返回0
注意: 只使用ANSI C/ANSI C++ 標準,不要呼叫依賴於編譯環境或作業系統的特殊函式。
注意: 所有依賴的函式必須明確地在原始檔中 #include <xxx>, 不能通過工程設定而省略常用標頭檔案。


提交時,注意選擇所期望的編譯器型別。

DFS搜尋。

#include<stdio.h>
long long ans;
int n,m,k;
int a[55][55];
const int INF=0x3f3f3f3f;
void dfs(int x,int y,int pre,int max)
{
    if(pre>k)
        return ;
    if(x==n-1&&y==m-1)
    {
        if(pre==k||(pre==k-1&&max<a[x][y]))//走到終點時剛好拿到了K件禮物或者拿到了k-1件禮物,在該點的禮物的價值又大於之前拿到的最大價值。此時方案數加一。
            ans++;
        return ;
    }
    if(x<n-1)//向下走
    {
        if(a[x][y]>max)
            dfs(x+1,y,pre+1,a[x][y]);
        dfs(x+1,y,pre,max);
    }
    if(y<m-1)//向右走
    {
        if(a[x][y]>max)
            dfs(x,y+1,pre+1,a[x][y]);
        dfs(x,y+1,pre,max);
    }
}
int main()
{
    while(~scanf("%d%d%d",&n,&m,&k))
    {
        for(int i=0; i<n; i++)
            for(int j=0; j<m; j++)
                scanf("%d",&a[i][j]);
        ans=0;
        dfs(0,0,0,-INF);
        printf("%lld\n",ans%1000000007);
    }
    return 0;
}<span style="color:#ff0000;">
</span>

上面的程式碼是普通的DFS搜尋。

記憶化搜尋:

<span style="font-size:14px;">#include<stdio.h>  
#include<string.h>  
int n,m,k;  
int a[55][55][15][15];  
int map[55][55];  
int dfs(int x,int y,int pre,int max)  
{  
    if(a[x][y][pre][max+1]>=0)  
        return a[x][y][pre][max+1];  
    int sum=0;  
    if(x==n-1&&y==m-1)  
    {  
        if(pre==k||(pre==k-1&&max<map[x][y]))  
        {  
            sum++;  
            sum%=1000000007;  
        }  
        a[x][y][pre][max+1]=sum;  
        return a[x][y][pre][max+1];  
    }  
    if(x<n-1)  
    {  
        if(map[x][y]>max)  
            sum+=dfs(x+1,y,pre+1,map[x][y]);  
        sum+=dfs(x+1,y,pre,max);  
        sum%=1000000007;  
    }  
    if(y<m-1)  
    {  
        if(map[x][y]>max)  
            sum+=dfs(x,y+1,pre+1,map[x][y]);  
        sum+=dfs(x,y+1,pre,max);  
        sum%=1000000007;  
    }  
    a[x][y][pre][max+1]=sum%1000000007;  
    return a[x][y][pre][max+1];  
}  
int main()  
{  
    while(~scanf("%d%d%d",&n,&m,&k))  
    {  
        memset(a,-1,sizeof(a));  
        for(int i=0; i<n; i++)  
            for(int j=0; j<m; j++)  
                scanf("%d",&map[i][j]);  
        dfs(0,0,0,-1);  
        printf("%lld\n",a[0][0][0][0]%1000000007);  
    }  
    return 0;  
}  </span>


10.標題:小朋友排隊


    n 個小朋友站成一排。現在要把他們按身高從低到高的順序排列,但是每次只能交換位置相鄰的兩個小朋友。


    每個小朋友都有一個不高興的程度。開始的時候,所有小朋友的不高興程度都是0。


    如果某個小朋友第一次被要求交換,則他的不高興程度增加1,如果第二次要求他交換,則他的不高興程度增加2(即不高興程度為3),依次類推。當要求某個小朋友第k次交換時,他的不高興程度增加k。


    請問,要讓所有小朋友按從低到高排隊,他們的不高興程度之和最小是多少。


    如果有兩個小朋友身高一樣,則他們誰站在誰前面是沒有關係的。


【資料格式】


    輸入的第一行包含一個整數n,表示小朋友的個數。
    第二行包含 n 個整數 H1 H2 … Hn,分別表示每個小朋友的身高。
    輸出一行,包含一個整數,表示小朋友的不高興程度和的最小值。


例如,輸入:
3
3 2 1
程式應該輸出:
9


【樣例說明】
   首先交換身高為3和2的小朋友,再交換身高為3和1的小朋友,再交換身高為2和1的小朋友,每個小朋友的不高興程度都是3,總和為9。




【資料規模與約定】
    對於10%的資料, 1<=n<=10;
    對於30%的資料, 1<=n<=1000;
    對於50%的資料, 1<=n<=10000;
    對於100%的資料,1<=n<=100000,0<=Hi<=1000000。




資源約定:
峰值記憶體消耗 < 256M
CPU消耗  < 1000ms




請嚴格按要求輸出,不要畫蛇添足地列印類似:“請您輸入...” 的多餘內容。


所有程式碼放在同一個原始檔中,除錯通過後,拷貝提交該原始碼。


注意: main函式需要返回0
注意: 只使用ANSI C/ANSI C++ 標準,不要呼叫依賴於編譯環境或作業系統的特殊函式。
注意: 所有依賴的函式必須明確地在原始檔中 #include <xxx>, 不能通過工程設定而省略常用標頭檔案。


提交時,注意選擇所期望的編譯器型別。

樹狀陣列和歸併排序的應用,還不會……

相關推薦

2014藍橋B(C/C++)預賽題目個人答案(歡迎指正)

1.標題:啤酒和飲料     啤酒每罐2.3元,飲料每罐1.9元。小明買了若干啤酒和飲料,一共花了82.3元。     我們還知道他買的啤酒比飲料的數量少,請你計算他買了幾罐啤酒。     注意:答案是一個整數。請通過瀏覽器提交答案。     不要書寫任何多餘的內容(例如:

2014藍橋JavaB省賽試題解析

包括 分數 年齡 dex 傳統 check 小學 位數 最大 題目及解析如下: 題目大致介紹: 第一題到第三題以及第六題是結果填空,方法不限只要得到最後結果就行 第四題和第五題是代碼填空題,主要考察算法基本功和編程基本功 第七題到第十題是編程題,要求編程解決問題

2014藍橋JAVA/JAVA++程式設計本科B決賽 出棧次序(結果填空)

出棧次序 X星球特別講究秩序,所有道路都是單行線。一個甲殼蟲車隊,共16輛車,按照編號先後發車,夾在其它車流中,緩緩前行。 路邊有個死衚衕,只能容一輛車通過,是臨時的檢查站,如圖【p1.png】所示。 X星球太死板,要求每輛路過的車必須進入檢查站,也可能不檢查就放行,也可能仔細檢查。 如果車輛進

2014藍橋C/C++程式設計本科B決賽 出棧次序(結果填空)

2014年第五屆藍橋杯C/C++程式設計本科B組決賽題目彙總: 出棧次序 X星球特別講究秩序,所有道路都是單行線。一個甲殼蟲車隊,共16輛車,按照編號先後發車,夾在其它車流中,緩緩前行。 路邊有

2014藍橋C/C++程式設計本科B決賽 生物晶片(程式設計大題)

2014年第五屆藍橋杯C/C++程式設計本科B組決賽題目彙總: 生物晶片 X博士正在研究一種生物晶片,其邏輯密集度、容量都遠遠高於普通的半導體晶片。 博士在晶片中設計了 n 個微型光源,每個光源

2014藍橋試題(Java本科B)

1.標題:武功祕籍     小明到X山洞探險,撿到一本有破損的武功祕籍(2000多頁!當然是偽造的)。他注意到:書的第10頁和第11頁在同一張紙上,但第11頁和第12頁不在同一張紙上。     小明只想練習該書的第81頁到第92頁的武功,又不想帶著整本書。請問他至少要撕下多

2013藍橋B(C/C++)預賽題目個人答案(歡迎指正)

第一題: 題目標題: 高斯日記     大數學家高斯有個好習慣:無論如何都要記日記。     他的日記有個與眾不同的地方,他從不註明年月日,而是用一個整數代替,比如:4210     後來人們知道,

2015藍橋省賽(C/C++ B)解題報告

第1題:統計不含4的數字 題目大意   統計10000至99999中,不包含4的數值個數。 題解   (@『落』常笑鷹 提供)直接推匯出數學公式   最高位除了0、4不能使用,其餘8個數字(1,2,3,5,6,7,8,9)均能使用,剩下的四位(

藍橋 表格計算 2016藍橋javaB決賽

標題:表格計算 某次無聊中, atm 發現了一個很老的程式。這個程式的功能類似於 Excel ,它對一個表格進行操作。 不妨設表格有 n 行,每行有 m 個格子。 每個格子的內容可以是一個正整數,也可以是一個公式。 公式包括三種: 1. SUM(x1,y1:x2,y2)

2015藍橋JavaB決賽題解——穿越雷區

標題:穿越雷區 X星的坦克戰車很奇怪,它必須交替地穿越正能量輻射區和負能量輻射區才能保持正常運轉,否則將報廢。 某坦克需要從A區到B區去(A,B區本身是安全區,沒有正能量或負能量特徵),怎樣走才能路徑最短? 已知的地圖是一個方陣,上面用字母標出了A,B區,其它區都標了正號或

2017藍橋 A(分巧克力)(二分)

9. 標題: 分巧克力    兒童節那天有K位小朋友到小明家做客。小明拿出了珍藏的巧克力招待小朋友們。    小明一共有N塊巧克力,其中第i塊是Hi x Wi的方格組成的長方形。    為了公平起見,小明需要從這 N 塊巧克力中切出K塊巧克力分給小朋友們。切出的巧克力需要滿足

藍橋BC/C++_獎券數目

獎券數目 有些人很迷信數字,比如帶“4”的數字,認為和“死”諧音,就覺得不吉利。 雖然這些說法純屬無稽之談,但有時還要迎合大眾的需求。某抽獎活動的獎券號碼是5位數(10000-99999), 要求其中

藍橋BC++試題

4.  格子中輸出 StringInGrid函式會在一個指定大小的格子中列印指定的字串。 要求字串在水平、垂直兩個方向上都居中。 如果字串太長,就截斷。 如果不能恰好居中,可以稍稍偏左或者偏上一點。 下面的程式實現這個邏輯,請填寫劃線部分缺少的程式碼。 #include <stdio.h> #in

藍橋 穿越雷區 2015藍橋JavaB決賽四題

標題:穿越雷區 X星的坦克戰車很奇怪,它必須交替地穿越正能量輻射區和負能量輻射區才能保持正常運轉,否則將報廢。 某坦克需要從A區到B區去(A,B區本身是安全區,沒有正能量或負能量特徵),怎樣走才能路徑最短? 已知的地圖是一個方陣,上面用字母標出了A,B區,其它區都標了正號

2017藍橋B省賽六題:最大公共子串

第六題 標題:最大公共子串 最大公共子串長度問題就是: 求兩個串的所有子串中能夠匹配上的最大長度是多少。 比如:"abcdkkk" 和 "baabcdadabc", 可以找到的最長的公共子串是"a

藍橋B國賽總結

第七屆省二,第八屆靠運氣省一進國賽。本來以為會在北大比賽,結果在北(方工業)大。 食物據說很難吃,就直接留在那裡了。 Dev還被強行綁了快捷鍵。 能來帝都一次還是很不錯的。跟著dalao們夜裡的小紅車編隊騎行。 第一題:0-9 A-Z 36進位制

2017藍橋JavaB省賽試題解析

font 藍橋杯 第一題 nbsp size 代碼 解決 省賽 style 題目及解析如下: 題目大致介紹: 第一題到第四題是結果填空,方法不限只要得到最後結果就行 第五題和第六題是代碼填空題,主要考察算法基本功和編程基本功 第七題到第十題是編程題,要求編程解決問題

藍橋2014決賽C_C++程式設計本科B

1.年齡巧合 小明和他的表弟一起去看電影,有人問他們的年齡。小明說:今年是我們的幸運年啊。我出生年份的四位數字加起來剛好是我的年齡。表弟的也是如此。已知今年是2014年,並且,小明說的年齡指的是

問題 1436: [藍橋][2014真題]地宮取寶

題目描述 X  國王有一個地宮寶庫。是  n  x  m  個格子的矩陣。每個格子放一件寶貝。每個寶貝貼著價值標籤。  地宮的入口在左上角,出口在右下角。  小明被帶到地宮的入口,國王要求他只能向右或向下行走。  走過某個格子時,如果那個格子中的寶貝價值比小明手中任意寶貝價

c語言網-1431-[藍橋][2014真題]分糖果

題目描述 問題描述 有n個小朋友圍坐成一圈。老師給每個小朋友隨機發偶數個糖果,然後進行下面的遊戲: 每個小朋友都把自己的糖果分一半給左手邊的孩子。 一輪分糖後,擁有奇數顆糖的孩子由老師補給1個糖果,從而變成偶數。 反覆進行這個遊戲,直到所有小朋友的糖果數都相同為止。 你的任