Poj 1664
问题分析
- 划分问题,即至少一个盘子没有使用和盘子全部使用;
分解问题
由1 可将问题化解为
a. 【m,n-1】至少一个盘子未使用
b. 【m-n,n】先将每个盘子放入一个苹果确保n个盘子被用,之后问题变为把m-n个苹果放入n个盘子;确定状态
dp[m][n] 表示m个苹果放入n个盘子的情况数;状态向量一般为和为和题相关的各个变量的一组取值;确定边界值
dp[m][0],,dp[m][1];
dp[0][n],,dp[1][n];
可由2确定边界位置,由实际情况推出边界的值- 确定状态转移方程
dp[m][n]=dp[m][n-1]+dp[m-n][n] - dp类问题特点
a. 最优子结构
– 每一个状态的值都由与之相关的状态的最优值确定
b.无后效性
– 当前状态只与其状态值有关,与得到值的路径无关
实现
#include <stdio.h>
#define MMAX 11
#define NMAX 11
int Table[MMAX][NMAX];//dp表
int make(int m,int n)//一次问题求解
{
/*for(int i=0;i<=m;i++)
{
for(int j=0;j<=n;j++)
{
Table[i][j]=1;
}
}*///代码垃圾请自行忽略
for(int i=0;i<=m;i++)//初始化边界
{
Table[i][1]=1;
Table[i][0]=1;
}
for(int j=0;j<=n;j++)//初始化边界
{
Table[1][j]=1;
Table[0][j]=1;
}
for(int i=2;i<=m;i++)//递推过程
{
for(int j=2;j<=n;j++)
{
if(i<j)
{
Table[i][j]=Table[i][i];
}
else
{
Table[i][j]=Table[i][j-1]+Table[i-j][j];
}
}
}
return Table[m][n];
}
int main()
{
int z,m,n;
scanf("%d",&z);
while(z--)
{
scanf("%d %d",&m,&n);
printf("%d\n",make(m,n));
}
return 0;
}