動態規划專題 多階段決策問題 藍橋杯 K好數


問題描述

如果一個自然數N的K進制表示中任意的相鄰的兩位都不是相鄰的數字,那么我們就說這個數是K好數。求L位K進制數中K好數的數目。例如K = 4,L = 2的時候,所有K好數為11、13、20、22、30、31、33 共7個。由於這個數目很大,請你輸出它對1000000007取模后的值。

輸入格式

輸入包含兩個正整數,K和L。

輸出格式

輸出一個整數,表示答案對1000000007取模后的值。

樣例輸入

4 2

樣例輸出

7

數據規模與約定

對於30%的數據,KL <= 106

對於50%的數據,K <= 16, L <= 10;

對於100%的數據,1 <= K,L <= 100。

 動態規划中多階段決策問題的思想是每做一次決策(即一個階段)就可以得到解的一部分,那么當所有的決策做完后,完整的解就出現了。

我們以此題為例,來看如何實現該問題的過程。

先簡單將題意理解一下就是要求的整個數字串中每一個數字相鄰的位置它們的數字不相鄰的數字串的個數。

簡單地來說,把題目的規模先減小,讓自己好思考整個題目的思路。

比如如果長度是1,那么除了0之外的數字都可以填入。

如果長度為2呢,我這時必須知道兩件事,第一它不相鄰的數字有哪些(前一位),第二前一位某個數字以它為終點它所有的滿足條件的總數。可以發現我要完成第二步是一定要用到第一步的。

即每個階段由上一個階段決定。

如果是長度3呢,當然也必須用到長度2的階段的解。

我們用一個二維數組圖來表示這樣的過程。

 

當然這題還有一個坑點,如果你想用上一階段的SUM減去某幾個不符合的值的話,很有可能出現由於值過大,已經取模的值減去兩個很大的值而出現負數,這時最好的解決辦法是全用循環加,不要出現減。

 

代碼如下:

 1 #include<iostream>
 2 #include<cstdio>
 3 #define MAXN 105 
 4 #define MOD %1000000007
 5 using namespace std;
 6 long long dp[MAXN][MAXN];
 7 int main()
 8 {
 9     long long i,j,k,c,l,sum=0;
10     cin>>k>>l;
11     //初始化第一個格子 
12     dp[0][1]=0; 
13     for(i=1;i<k;i++)
14         dp[i][1]=1;
15     sum=k-1;
16     for(i=2;i<=l;i++)
17     {//格子
18         for(j=0;j<k;j++)
19         {
20             if(j==0)
21             {
22                 dp[j][i]=(dp[j][i]+(dp[j][i-1])MOD)MOD;
23                 for(c=2;c<k;c++) 
24                     dp[j][i]=(dp[j][i]+(dp[c][i-1])MOD)MOD;  //必須循環加,用sum減去一些值會負溢出!!
25             }
26             else if(j==k-1)
27             {
28                 for(c=0;c<k-2;c++)
29                     dp[j][i]=(dp[j][i]+(dp[c][i-1])MOD)MOD;
30                 dp[j][i]=(dp[j][i]+(dp[j][i-1])MOD)MOD;
31             }
32             else
33             {
34                 for(c=0;c<k;c++)
35                 {
36                     if(c!=j-1&&c!=j+1)
37                         dp[j][i]=(dp[j][i]+(dp[c][i-1])MOD)MOD;
38                 }
39             }
40             //cout<<dp[j][i]<<" ";
41          } 
42          sum=0;
43          for(j=0;j<k;j++)
44              sum=((sum)MOD+(dp[j][i])MOD)MOD;
45         // cout<<endl; 
46         //cout<<sum<<endl;
47     }
48     cout<<sum<<endl;
49     return 0;
50 }

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM