zoukankan      html  css  js  c++  java
  • [wikioi]数的划分

    http://wikioi.com/problem/1039/

    划分型DP。最终的思路是,F[i][j]表示i分成j份,如果分出来的有1,那么去掉1,就是F[i-1][j-1];如果没有1,那就都减1,就是F[i-j][j](注意此时i>=2j)。那么F[i][j]=F[i-1][j-1]+F[i-j][j]
    详细些的话,以sample为例:
    7=5+1+1;
    7=2+4+1;
    7=3+3+1;
    7=2+2+3;
    我们可以把所有数的拆分分成2种情况,有1和没有1的2种
    那么有1的部分全部减去1,变成
    6=5+1;
    6=2+4;
    6=3+3;
    这就是6的所有划分成2部分的划分了。
    没有1的,我们把没有1的所有因子全部减去1
    得到4=1+1+2;
    这就是4的所有划分成3部分的划分了

    这个推导其实一时难以想到,这篇文章里有个转化和推导,图有点意思,虽然最终还是上面的简洁直接:http://blog.csdn.net/re_cover/article/details/9383177
    关于怎么想到F[i-j][j]这样的东西的,某人说,N个球放到K个盒子,因为盒子不为空,那么我先把每个盒子放一个球。这也是某种思路的来源吧。

    #include <cstdio>
    #include <iostream>
    #include <algorithm>
    #include <memory.h>
    #define MAX(a, b) a>b?a:b
    #define LEN_N 205
    #define LEN_K 10
    using namespace std;
     
    int F[LEN_N][LEN_K];
    int N;
    int K;
     
    void init()     
    {
        scanf("%d%d", &N, &K);
        for (int i = 1; i <= N; i++)
            for (int j = 1; j <= K; j++)
                F[i][j] = -1;
    }   
    
    int dp(int i, int j)  
    {
        // F[i][j] = F[i-1][j-1] + F[i-j][j];
        if (i < j || i == 0 || j == 0) return 0;
        if (i == j) return 1;
        if (F[i][j] != -1) return F[i][j];
        F[i][j] = dp(i-1, j-1) + dp(i-j, j);
        return F[i][j];
    }
     
    int main()
    {
        init();
        
        int ans = dp(N, K);
        printf("%d
    ", ans);
        return 0;
    }
    

      

  • 相关阅读:
    全球2/3的DNS瘫痪 顶级域名根服务器故障
    PHP多种形式发送邮件
    IOS开发的基础知识
    Java数字图像处理基础
    将HTML5 Canvas的内容保存为图片
    C# SortedList类概念和示例
    实例对比剖析c#引用参数的用法
    如何理解css中的float
    创建Google网站地图Sitemap.xml
    c#生成静态html文件,封装类
  • 原文地址:https://www.cnblogs.com/lautsie/p/3383257.html
Copyright © 2011-2022 走看看