原**小結劃分數如何dp
1.hdu 1028 整數劃分
首先,我們引進乙個小小概念來方便描述吧,dp[n][m]是把自然數劃劃分成所有元素不大於m的分法,例如:
當n=4,m=1時,要求所有的元素都比m小,所以劃分法只有1種:;
當n=4,m=2時,只有3種,,;
當n=4,m=3時,只有4種,,,;
當n=4,m=5時,只有5種,,,,;
從上面我們可以發現:當n==1||m==1時,只有一種分法;
當n < m時,由於分法不可能出現負數,所以dp[n][m]=dp[n][n];
當n==m時,那麼就得分析是否要分出m這乙個數,如果要分那就只有一種,要是不分,那就是把n分成不大於m-1的若干份;即dp[n][n]=1+dp[n][n-1];
當n>m時,那麼就得分析是否要分出m這乙個數,如果要分那就,}時n-m的分法dp[n-m][m],要是不分,那就是把n分成不大於m-1的若干份;即dp[n][n]=dp[n-m][m]+dp[n][m-1];
**:
#includeusing namespace std;
#define maxn 121
int dp[maxn][maxn]=;
int main()
}int n;
while(scanf("%d",&n)!=eof)printf("%d\n",dp[n][n]);
return 0;
}
ps:這題也可以母函式做,參考:
2.cdoj 1307 abcde
題意:
在數電中,有一種碼,類似bcd碼這種玩意兒
第i位如果為1的話,那麼ans+=a[i],a[i]是這一位的位權
然後現在給你乙個n,問你一共有多少種碼可以表示1~n的所有數呢?
1,1,2和2,1,1視作一樣。
解法:
dp預處理
首先考慮這個東西,如果不視作一樣的話,就很簡單了
dp[i]表示當前和為i的方案數,顯然這個玩意兒能夠一直轉移到2i-1去。(比如5,你轉移到最大的肯定是3,不然就無法表示出1,2,3,4,5每個數了,這很顯然)
由於視作一樣,那麼我們只要維護乙個當前的最大值就好了,保證這個序列是遞增的,這樣就都不會一樣了。
dp[i][j]表示現在和為i,最大值為j的方案數有多少。
轉移方程:
dp[i][j]=(dp[i−1][j−1]+dp[i−j][j])
前者表示由沒有最大值j轉移過來,後者表示從有最大值j轉移過來
#include using namespace std;
typedef long long ll;
const int mod = 1e9+7;
long long dp[5010][5010];
long long ans[5010];
int main()
}int t;
scanf("%d", &t);
while(t--)
return 0;
}
3.687c the values you can make
題意:給n個各有價值的硬幣,要從它們中選出若干個組合成面值k,而要求的是各個方案裡這些選出的硬幣能組合出來的面值有哪些
dp[i][j][k]表示到第i個硬幣,和為j,組成面值為k這種情況是否存在。
要用滾動陣列寫,不然要爆記憶體
詳細可以看題解:
**:
#include using namespace std;
#define ff first
#define ss second
#define pb push_back
#define ll long long
#define mod 1000000007
#define ull unsigned long long
#define mst(ss,b) memset(ss,b,sizeof(ss));
#define pl(x) cout << #x << "= " << x << endl;
const int inf=0x3f3f3f3f;
const int n=505;
bool dp[2][n][n];//第i個 和為j 組成面額為k
int n, k, c[n], cnt;
int ans[n];
int main()}}
for(int i=0; i<=k; i++)
printf("%d\n", cnt);
for(int i=1; i<=cnt; i++)printf("%d ", ans[i]);
return 0;
}
4.51nod 1201 整數劃分
思路:
dp[i][j]表示i這個數劃分成j個數的情況數。
dp[i][j] = dp[i - j][j] + dp[i - j][j - 1]
前者表示將i - 1劃分為j個數,然後j個數都+1 還是不重複
後者表示將i - 1劃分為j - 1個數,然後j - 1個數都+1,再加上1這個數
普通的dp是o(n^2)的,但是可以發現1 + 2 + … + m = n , (1 + m)m = n 2,j只要遍歷sqrt(n * 2)個就好了。所以複雜度為o(n*sqrt(n*2))
#include using namespace std;
#define mod 1000000007
templatevoid read(t&num)
const int n=5e4+10;
int dp[n][351], n;
int main()
}} int ans = 0;
for(int i = 1; i < 350; i++)
ans = (ans + dp[n][i]) % mod;
printf("%d\n", ans);
return 0;
}
整數劃分 劃分數(DP動態規劃)
給你乙個正整數n,讓你計算出n的m劃分有幾種方法。思路 定義dp i j 為i的j劃分,即將i劃分為j個數字之和的方案數。1 當j i時,此時,劃分個數不超過i,此時是正常的劃分。劃分的結果一定只有兩種型別 一種是j個數字,都大於0。另一種是有0,即不夠劃分j個,用0來湊的。j個數字中存在0的,其實...
整數劃分(數的m劃分)
includeusing namespace std int f int n,int m n代表數字,m代表n的m劃分 int main 方式二 動態規劃 dp i j 表示i的j次劃分的情況種數 狀態轉移方程為dp i j dp i j j dp i 1 j 1 1.dp i 1 j 1 表示劃分...
整數劃分(劃分dp)總結
寫了幾個題發現整數劃分是一類題,而不是一道題。具體題型 1 n相同元素放入m個相同的盤子 盤子允許為空 例題 放蘋果 poj 1664設dp i j 為 j 個元素放入i個盤子轉移方程 dp i j dp i 1 j 新新增乙個盤子,盤子為空 dp i j dp i j i i個盤子 各取出乙個 2...