递推关系的运用加简单DP【UVA11137Ingenuous Cubrency】-------2015年1月27日

一:题意描述

本题就是求立方数之和。输入正整数n,求将n写成若干个正整数的立方和有多少种方法?

二:问题分析

本题主要的难点就是确定状态。我们可以建立多段图。节点(i,j)表示“使用不超过i的整数的立方,累加和为j“这个状态。设d(i,j)表示为从(0,0)到(i,j)的路径条数,最终答案

是d(21,n)。对于这个图而言,每一个节点(i,j)都只能从当前节点(i,j)到达节点(i+1,a*(j+1)^3+j)(a为j+a*(j+1)^3<maxn的常数)所以我们可以写出如下代码:

#include<iostream>
#include<string.h>
#include<math.h>
#include<algorithm>
using namespace std;
#define MAXI 21
#define  MAXN 10000+5
long long d[MAXI+1][MAXN];
int main()
{
    int n;
    memset(d,0,sizeof(d));
    d[0][0]=1;
    for(int i=1;i<=MAXI;i++)
    {
        for(int j=0;j<=MAXN;j++)
        {
            for(int a=0;j+a*i*i*i<=MAXN;a++)
                d[i][j+a*i*i*i]+=d[i-1][j];
        }
    }
    while(cin>>n)
    {
        cout<<d[21][n]<<endl;
    }
}

但是我们可以分析得出这个代码的时间复杂度接近O(N^3).所以我们应该把这个问题加以改进:

对于第i个数字而言,我们可以这样分析:如果我们取一次第i个数字得到d(i,j)那么可以知道这是从状态d(i,j-i^3)转化得到;当我们不取第i个数字得到d(i,j)那么可以知道这是从状态d(i-1,j)转化得到。那么我们便可以得到递推公式:d(i,j)=d(i-1,j)+d(i,j-i^3)(如果大家想说我们如果需要用多个i^3怎么办?是不是这个公式不在成立呢?仔细想想还是成立的,因为我们如果再往下递推一层或者多层我们便可以使用多次i^3,那么我们便可以把代码写成如下形式:时间复杂度仅仅是O(n^2),而且我们可以用滚动数组节约存储空间。

下面给出代码:

#include<iostream>
#include<string.h>
#include<math.h>
#include<algorithm>
using namespace std;
#define  MAXN 22*22*22
long long dp[MAXN];
int main()
{
    int n;
    memset(dp,0,sizeof(dp));
    long long c[22];
    for(int i=1;i<22;i++)
        c[i]=i*i*i;
    dp[0]=1;
    for(int i=1;i<22;i++)
        for(int j=c[i];j<MAXN;j++)
        dp[j]+=dp[j-c[i]];
    while(cin>>n)
    {
        cout<<dp[n]<<endl;
    }
}

在合理选取递推式和状态时往往可以节省很多时间,提高效率。

时间: 2024-08-06 01:29:59

递推关系的运用加简单DP【UVA11137Ingenuous Cubrency】-------2015年1月27日的相关文章

UVA1401 (字典树加简单dp)

#pragma GCC optimize(2) #include <bits/stdc++.h> #define ll long long using namespace std; const int N = 5e5+10; const int mod=20071027; const int sigma_size=26; int dp[N]; char str[N]; char s[105]; struct Trie{ int ch[N][sigma_size]; int val[N]; in

2015年6月7日 vs项目加载失败。提示需要下载IIS

问题如图: 在项目上右键编辑: 找到UseIIS节点,将true改为false 然后重新加载就ok了

(hdu step 3.2.2)Common Subsequence(简单dp:求最长公共子序列的长度)

在写题解之前给自己打一下广告哈~..抱歉了,希望大家多多支持我在CSDN的视频课程,地址如下: http://edu.csdn.net/course/detail/209 题目: Common Subsequence Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 65536/32768 K (Java/Others) Total Submission(s): 976 Accepted Submission(s): 538   Probl

(hdu step 3.2.8)命运(简单DP:求从左上角走到右下角的最大值)

题目: 命运 Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others) Total Submission(s): 1247 Accepted Submission(s): 530   Problem Description 穿过幽谷意味着离大魔王lemon已经无限接近了!可谁能想到,yifenfei在斩杀了一些虾兵蟹将后,却再次面临命运大迷宫的考验,这是魔王lemon设下的又一个机关.要知道,

(hdu step 2.3.7)下沙的沙子有几粒?(简单DP:求有m个H,n和D,且任意索引上H的个数都要比D的个数多的方案数)

在写题解之前给自己打一下广告哈~..抱歉了,希望大家多多支持我在CSDN的视频课程,地址如下: http://edu.csdn.net/course/detail/209 题目: 下沙的沙子有几粒? Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 65536/32768 K (Java/Others) Total Submission(s): 894 Accepted Submission(s): 505   Problem Descri

(hdu step 3.2.1)Max Sum(简单dp:求最大子序列和、起点、终点)

在写题解之前给自己打一下广告哈~..抱歉了,希望大家多多支持我在CSDN的视频课程,地址如下: http://edu.csdn.net/course/detail/209 题目: Max Sum Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 65536/32768 K (Java/Others) Total Submission(s): 1390 Accepted Submission(s): 542   Problem Descrip

UVA1025---A Spy in the Metro(简单dp)

dp[i][j]表示时刻i,在车站j,等待的最少时间 有3种方案: 等一分钟 往左搭车 往右搭车 /************************************************************************* > File Name: uva1025.cpp > Author: ALex > Mail: [email protected] > Created Time: 2015年05月25日 星期一 19时05分09秒 ***********

hdu4826---Labyrinth(简单dp)

Problem Description 度度熊是一只喜欢探险的熊,一次偶然落进了一个m*n矩阵的迷宫,该迷宫只能从矩阵左上角第一个方格开始走,只有走到右上角的第一个格子才算走出迷宫,每一次只能走一格,且只能向上向下向右走以前没有走过的格子,每一个格子中都有一些金币(或正或负,有可能遇到强盗拦路抢劫,度度熊身上金币可以为负,需要给强盗写欠条),度度熊刚开始时身上金币数为0,问度度熊走出迷宫时候身上最多有多少金币? Input 输入的第一行是一个整数T(T < 200),表示共有T组数据. 每组数据

2014 HDU多校弟九场I题 不会DP也能水出来的简单DP题

听了ZWK大大的思路,就立马1A了 思路是这样的: 算最小GPA的时候,首先每个科目分配到69分(不足的话直接输出GPA 2),然后FOR循环下来使REMAIN POINT减少,每个科目的上限加到100即可 算最大GPA的时候,首先每个科目分配到60分,然后FOR循环下来使REMAIN POINT减少,每个科目的上限加到85即可,如果还有REMAIN POINT,就FOR循环下来加到100上限即可 不会DP 阿 QAQ 过段时间得好好看DP了  =  = 于是默默的把这题标记为<水题集> //