引用一个博客点击打开链接看看题目
第一题:
1269: 划分数
Time Limit: 1 Sec Memory Limit: 128 MB
[ Submit][ Status][ Web Board]
Problem Description
将整数n分成m份,求划分的种数,注意每份不为空,不考虑顺序。
比如整数4的划分,1 1 2 和 1 2 1 以及2 1 1 为同一种划分。
Input
多组测试样例,每组两个整数。n和m。(6<n<=200,2<=m<=6)
Output
每组测试样例输出一行。输出一个整数表示划分的种数。
Sample Input
7 3
Sample Output
4
HINT
7的划分有{1,1,5;1,2,4;1,3,3;2,2,3}
题目意思就不多说了,只给一个dp方程: dp[i][j]=dp[i-1][j-1]+dp[i-j][j].自己慢慢yy吧,意思就是说把n分成m份这个状态可以看作是
1.将n-1分成m-1后面还有一个1
2.将dp[n][m]里面所有的元素都减去1,就是dp[n-m][m]
递推方程为dp[i][j]=dp[i-1][j-1]+dp[i-j][j]
代码:
#include<iostream>
#include<cstring>
using namespace std;
int dp[205][205];
int main()
{
int i,j;
memset(dp,0,sizeof(dp));
dp[1][1]=1;
for(i=2;i<=200;i++)
{
int mi=min(i,10);
for(j=1;j<=mi;j++)
dp[i][j]=dp[i-1][j-1]+dp[i-j][j];
}
int a,b;
while(cin>>a>>b)
cout<<dp[a][b]<<endl;
return 0;
}
第二题:n个无区分的物品,分成不超过m组划分成M的余数;
eg:n=4,m=3;答案4(1+1+2,1+3 , 2+2 ,4)
代码
#include <iostream>
using namespace std;
const int maxn=10000+5;
int dp[maxn][maxn];
int main()
{
int n,m;
cin>>n>>m;
dp[0][0]=1;
for(int i=1;i<=m;i++)
for(int j=0;j<=n;j++)
{
if(j>=i)
dp[i][j]=dp[i][j-i]+dp[i-1][j];
else
dp[i][j]=dp[i-1][j];
}
cout << dp[m][n] << endl;
return 0;
}
第三题 Poj2229
之前以为是单纯的找出来的规律,现在发现确是包含了dp的想法
#include <iostream>
using namespace std;
const int maxn=1e9;
int dp[1000005];
int main()
{
int n;
dp[1]=1;
dp[2]=2;
for(int i=3;i<=1000000;i++)
{
if(i%2==1)dp[i]=dp[i-1]%maxn;
else
dp[i]=(dp[i-2]+dp[i/2])%maxn;
}
cin>>n;
cout<<dp[n];
return 0;
}
我的另一篇博客 sumsets点击打开链接