C++ 如何解决我的动态规划问题?

C++ 如何解决我的动态规划问题?,c++,dynamic-programming,C++,Dynamic Programming,这是我的密码: #include<bits/stdc++.h> using namespace std; typedef long long int lli; #define M 1000000007 #define INF 1000000007 typedef pair<lli,lli> ll; #define mem(a,x) memset(a,x,sizeof(a)) lli n,k,m; lli dist[507][507]; lli path1[207][207

这是我的密码:

#include<bits/stdc++.h>
using namespace std;
typedef long long int lli;
#define M 1000000007
#define INF 1000000007
typedef pair<lli,lli> ll;
#define mem(a,x) memset(a,x,sizeof(a))
lli n,k,m;
lli dist[507][507];
lli path1[207][207];
vector<int> v2(1005,1);
vector<double> v;
lli x,y,c,z,t,q,u,d,a1,b;
struct edge
{
    lli a,b,cost;
};
/*void djkstra(int x,vector<ll> v[])
{
    mem(vis,0);
    dist[x]=0;
    s2.insert({0,x});
    while(!s2.empty())
    {
        ll p=*s2.begin();
        s2.erase(s2.begin());
        x=p.second;
        if(vis[x])
        continue;
        vis[x]=1;
        for(int j=0;j<v[x].size();j++)
        {
            if(dist[v[x][j].second]>dist[x]+v[x][j].first)
            {
                dist[v[x][j].second]=dist[x]+v[x][j].first;
                s2.insert({dist[v[x][j].second],v[x][j].second});
                a[v[x][j].second]=x;
            }
        }
    }
}*/
lli parent[100007];
lli find(lli a)
{
    return a==parent[a]?a:parent[a]=find(parent[a]);
}
void dset(lli n)
{
    for(int j=0;j<=n;j++)
    parent[j]=j;
}
void unio(lli a,lli b,lli rank[])
{
    if(rank[find(a)]>rank[find(b)])
    parent[find(b)]=find(a);
    else if(rank[find(b)]>rank[find(a)])
    parent[find(a)]=find(b);
    else
    {
        parent[find(a)]=find(b);
        rank[find(b)]++;
    }
}
bool check(lli a)
{
    if((a1*a*m+b*(a-1)+d)>=x)
    return true;
    return false;
}
/*bool valid(int i,int x)
{
    for(int j=1;j<x;j++)
    {
        if((abs(b[j-1]-i)==abs(j-x))||(i==b[j-1])||(j==x))
        return false;
    }
    return true;
}*/
lli p[10007];
lli dp[301][301][301];
map<ll,ll> pat;
map<ll,lli> p2;
lli pr[200007],we[200007];
lli a[100005];
map<lli,lli> m4;
vector<int> v4;
int f=0;
lli tot=1;
lli vis[1001][1001];
lli p1;
lli s[10001];
lli n1;
lli solve(lli n,lli i,lli c)
{
//cout<<n<<" "<<i<<" "<<a[i]<<" "<<dp[n][i]<<endl;
if(i>n1)
return 0;
if(c==0&&n>0)
return 0;
if(c==0&&n==0)
return 1;
if(n<0)
return 0;
if(dp[n][i][c]!=-1)
return dp[n][i][c];
dp[n][i][c]=solve(n-i,i,c-1);
dp[n][i][c]+=solve(n,i+1,c);
return dp[n][i][c];
}
int main()
{
    while(1)
    {
        string s="\0";
        getline(cin,s);
        if(s.size()==0)
        return 0;
        string d[3];
        d[0]="\0";
        d[1]="\0";
        d[2]="\0";
        int c=0;
        for(int i=0;i<=300;i++)
        {
            for(int j=1;j<=300;j++)
            {
            for(int k=1;k<=300;k++)
            dp[i][j][k]=-1;
            }
        }
        for(int j=0;j<s.length();j++)
        {
            if(s[j]!=' ')
            d[c]+=s[j];
            else
            c++;
        }
        int f;
        stringstream ss(d[0]);
        ss>>f;
        n1=f;
        lli d1=0;
        for(int i=1;i<=f;i++)
        d1+=solve(f,1,i);
        for(int i=0;i<=300;i++)
        {
            for(int j=0;j<=300;j++)
            dp[0][i][j]=1;
        }
        lli sum[f+1];
        mem(sum,0);
        sum[0]=1;
        for(int i=1;i<=f;i++)
        {
            if(i==1)
            sum[i]=dp[f][1][i];
            else
            sum[i]=sum[i-1]+dp[f][1][i];
        }
        if(c==0)
        {
            if(f!=0)
            cout<<d1<<endl;
            else
            cout<<1<<endl;
        }
        else if(c==1)
        {
            int f1;
            stringstream ss1(d[1]);
            ss1>>f1;
            if(f1>f)
            f1=f;
            cout<<sum[f1]<<endl;
        }
        else
        {
            int f1,f2;
            stringstream ss1(d[1]);
            ss1>>f1;

            stringstream ss2(d[2]);
            ss2>>f2;
            if(f1>f)
            cout<<0<<endl;
            else
            {
            if(f2>f)
            f2=f;
            cout<<sum[f2]-sum[f1]+dp[f][1][f1]<<endl;
            }
        }
    }
}
我的解决方案是O(N^3),它应该通过测试用例(N=300),但仍然超过了时间限制

我怎样才能解决这个问题


这里是.

好的,所以动态编程能够重用已经完成的工作

那么如何重用代码呢

以下是我的想法:

假设总金额为6美元,我们知道我们总共有3件,最多合计该金额。你可以从一开始就尝试,找到一种方法,使总数达到1美元,而不是2美元,3美元。。总是重复使用你以前做过的事情。 范例

总共1美元 唯一方式1x1$(将其保存在内存中)

总共2美元 -分解成你可以添加的所有可能的2块:1+1,2 -要找到其他可能性,请重复使用在递归之前所做的操作(此级别的递归仅在第一次迭代后停止,因为1$是最小的美元值) -记住这一点

。。。(继续这样,总共3美元,总共4美元,总共5美元……)

总共6美元 -分解所有可能的2个部分,你可以添加:6,1+5,2+43+3(总是(n intDiv 2)+1个可能性) -要找到其他可能性,请重复使用之前所做的工作: 示例:对于3+3的可能性,请查看总计3美元的所有可能性,以找到所有可能性。 -删除所有使用过多碎片的可能性。 你最终找到了所有可能的答案:1+1+4、1+2+3、3+3和2+2+2


希望有帮助:)

时间限制是什么,目前需要多长时间?有这样神秘的名字有什么意义?你如何在考虑易读性的基础上重新格式化它,然后再问一次。@livepk21——许多在线编码网站都在推广这些不良的编码习惯。这里有上百篇帖子都有着相同的奇怪而神秘的名字:
typedef long long int lli;typedef对ll--这些东西不能使代码易于阅读或调试。如果有什么区别的话,它会使代码更容易出错。问题从来没有说明输入文件中的最大行数。使用固定时间查询执行
O(n^3)
DP应该可以。看起来你的代码太复杂了。如果我们将
dp[j][k]
定义为最多使用
k
硬币支付
j
美元的方式数,我们可以在
O(n^3)
时间内计算该数组,并使用该数组回答
O(1)
时间中的所有查询。他正在尝试进行记忆,虽然他的代码看起来非常复杂。哎呀,当他说代码是O(N^3)时,我并没有试着读那么多代码,我想在不到3秒钟的时间内,N=200没有记忆?我很惊讶。你做了吗?但是用动态编程,它可以快得多。是的,我做了。计算机每秒可以完成十亿次运算。300^3/10^9 = 0.027. O(n^3)
解决方案是动态规划。
lli solve(lli n,lli i,lli c)