给定长度和位数,我们必须找到可以做出的最小和最大数量?

时间:2015-07-22 04:58:12

标签: dynamic-programming

正如问题所述,我们给出一个正整数 M 和一个非负整数 S 。我们必须找到长度 M 的数字中最小和最大的数字,以及 S 的数字之和。

约束:

(S> = 0且S <= 900)

(M> = 1且M <= 100)

我想到了它并得出结论它必须是动态编程。但是我没能构建 DP状态

这就是我的想法: -

dp [i] [j] =第一个'i'数字加上'j'

并尝试制作程序。这就是它的样子

/*
  *** PATIENCE ABOVE PERFECTION ***
    "When in doubt, use brute force. :D"

    -Founder of alloj.wordpress.com

* /

#include<bits/stdc++.h>

using namespace std;

#define pb push_back

#define mp make_pair

#define nline cout<<"\n"

#define fast ios_base::sync_with_stdio(false),cin.tie(0)

#define ull unsigned long long int

#define ll long long int

#define pii pair<int,int>

#define MAXX 100009

#define fr(a,b,i) for(int i=a;i<b;i++)

vector<int>G[MAXX];


int main()
{
    int m,s;

    cin>>m>>s;

    int dp[m+1][s+1];

    fr(1,m+1,i)

     fr(1,s+1,j)

       fr(0,10,k)
          dp[i][j]=min(dp[i-1][j-k]+k,dp[i][j]); //Tried for Minimum

    cout<<dp[m][s]<<endl;

    return 0; 
}

请指导我关于这个DP状态以及该程序的时间复杂程度。这是我第一次尝试DP。

2 个答案:

答案 0 :(得分:0)

hotels.stream().map(i -> i.getMinSellingPrice()).min(Comparator.naturalOrder()).get());

答案 1 :(得分:-1)

DP状态是(i,j)。它可以被认为是根据递归定义的数学函数的参数(较小的问题,因此是子问题!)

更深刻, 状态通常是唯一识别问题的参数数量,因此我们总是知道我们在计算什么!!

让我们以你的问题为例

为了定义你的问题,我们需要状态中的数字+可以用这些数字形成的总和(注意:你有点在遍历数字的同时保持总和!)

我认为这对州政府来说已经足够了。

现在,

动态编程的运行时间非常简单。

首先让我们看看问题中存在多少子问题:

您需要填写每个州,即您必须涵盖小于或等于整个问题的所有独特子问题! 经常性关系已知哪个问题小于另一个问题!!

例如: 斐波那契序列

F(n)=F(n-1)+F(n-2)

注意基本情况,总是最小的子问题。!! 注意这里F(n)我们必须计算F(n-1)和F(n-2),并且它将达到n = 1的阶段,你需要返回基本情况!! 因此,子问题的总数可以说是基本案例和当前问题之间的所有问题!

现在, 在自下而上,我们需要在这个基本案例和问题之间处理每个州的大小!

现在,这告诉我们运行时间应该是

O(子问题数*每个子问题的时间)。

因此,您的解决方案DP [0] [0]到DP [M] [S]中存在多少个子问题 并且对于每个问题,您运行的循环为10

O(M * S(子问题)* 10)

砍那个常数! 但它总是不一定是常数!!

以下是您可能希望查看的一些代码!随意问什么!

#include<bits/stdc++.h>
using namespace std;
bool DP[9][101];
int Number[9][101];
int main()
{
    DP[0][0]=true;  // It is possible to form 0 using NULL digits!!
    int N=9,S=100,i,j,k;
    for(i=1;i<=9;++i)
        for(j=0;j<=100;++j)
        {
            if(DP[i-1][j])
            {
                for(k=0;k<=9;++k)
                    if(j+k<=100)
                        {
                            DP[i][j+k]=true;
                            Number[i][j+k]=Number[i-1][j]*10+k;
                        }
            }
        }
    cout<<Number[9][81]<<"\n";
    return 0;
}

您可以使用回溯而不是直接存储数字,因为您的约束很高!

DP[i][j]表示是否可以仅使用i数字形成数字之和!!

Number[i][j]

是我的懒惰以避免键入回溯方式(困了,已经是3 A.M.)

我正在尝试添加所有可能的数字来扩展状态。

它本质上是一种前卫的DP风格!您可以在Topcoder

了解更多相关信息