Poj 1664 dp

Poj 1664

链接


问题分析
  1. 划分问题,即至少一个盘子没有使用和盘子全部使用;
  2. 分解问题
    由1 可将问题化解为
    a. 【m,n-1】至少一个盘子未使用
    b. 【m-n,n】先将每个盘子放入一个苹果确保n个盘子被用,之后问题变为把m-n个苹果放入n个盘子;

  3. 确定状态
    dp[m][n] 表示m个苹果放入n个盘子的情况数;状态向量一般为和为和题相关的各个变量的一组取值;

  4. 确定边界值
    dp[m][0],,dp[m][1];
    dp[0][n],,dp[1][n];
    可由2确定边界位置,由实际情况推出边界的值

  5. 确定状态转移方程
    dp[m][n]=dp[m][n-1]+dp[m-n][n]
  6. 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;
}

猜你喜欢

转载自blog.csdn.net/m0_38062488/article/details/80636622