《训练指南》——6.9
Uva11137:
??立方體之和:輸入正整數n(n≤10000),求將n寫成若干個正整數的立方體之和有多少種方法。
??分析:這道題目其實就是基于遞推的一道動態規劃題目了,我們建立記錄多狀態的多段圖,利用d[i][j]來表示立方數的底數不超過i且最終和為j的方法數,結合n的取值,有21^3 > 10000,因此這里的最終答案便是d[21][n].
??下面我們面臨的問題就是如何求解d[i][j],即尋求遞推關系。對于d[i][j],我們分成如下的兩種情況:
(i)和式當中最大的底數是i-1,則有d[i-1][j]種情況。
(ii)和式當中最大的底數是i,則有d[i][j-i^3]種情況。
可以看到,d[i][j]基于的子狀態兩個維度的參數都小于或等于i、j,這放在動態規劃當中,叫做無后效性。
?
#include<cstdio>#include<cstring>using namespace std;int main(){long long d[23][10005];memset(d , 0 , sizeof(d));d[0][0] = 1;for(int i = 1;i < 23;i++)for(int j = 0;j < 10005;j++){if(j-i*i*i >= 0)d[i][j] = d[i-1][j] + d[i][j-i*i*i];elsed[i][j] = d[i-1][j];}// printf("%d\n",d[1][0]);int n;while(scanf("%d",&n) != EOF){printf("%lld\n",d[22][n]);}}?
?
Uva11375(需要高精度,還沒有A):
??火柴:用n(1≤n≤2000)根能夠組成多少個非負整數?
??分析:我們設置d[i]恰好用i根火柴擺出不同的非負整數的個數。F[n]是本題結果,則顯然有F[n] = ∑d[i]。因此現在我們面臨的問題是如何計算d[n]。
??我們用c[x]記錄拼出個位數x所需要的火柴數目,那么現在考察d[n]中的所有情況,為了便于找到遞推關系,我們都去掉每一個整數的個位,這樣我們能夠找到如下的狀態轉移方程,或者說是遞推方程:
??d[n] = ∑d[n-c[i]],i∈[0,9].
??但是在編碼實現的時候,并不是線性得求出d[1],d[2]…d[n],而是動態的更新d[1]、d[2]…的值,從狀態轉移方程中能夠看出,d[n]需要基于更小規模的子問題d[n-c[i]],因此這里我們首先設置一層循環遍歷1~n作為d[]下標的參數,然后再進行“添加尾數”的操作,這樣就有如下的狀態轉移方程:
??for i 0 to maxn
for j 0 to 9
??d[i+c[j]] += d[i]
簡單的參考代碼如下(Ps原題結果較大應用高精度運算):
?
#include<cstdio>#include<cstring>using namespace std;const int maxn = 2005;int main(){int c[10] = {6,2,5,5,4,5,6,3,7,6};int d[maxn];memset(d , 0 , sizeof(d));d[0] = 1;for(int i = 0;i < maxn;i++)for(int j = 0;j < 10;j++)if(!(i==0 && j==0) && i + c[j] < maxn)d[i+c[j]] += d[i];int n;while(scanf("%d",&n) != EOF){int sum = 0;for(int i = 1;i <= n;i++)sum += d[i];printf("%d\n",sum);}// printf("%d %d %d %d",d[2],d[3],d[4],d[5]); }?
轉載于:https://www.cnblogs.com/rhythmic/p/5576534.html
總結
以上是生活随笔為你收集整理的《训练指南》——6.9的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 无缝切换效果
- 下一篇: eclipse中多个工程编译到同一个目录