Week7 简单DP

Week7  简单DP

第一题(采药)

评析:仔细一看,就是照搬了一下01背包,连数据都不换,这里用了记忆化搜索来做

#include<bits/stdc++.h>

using namespace std;

int T,m,t[105],v[105],vis[105][1005];

int dfs(int i,int j)

{

       int ans=0;

       if (vis[i][j]!=-1) return vis[i][j];

       if (i==0) ans=0;//如果时间为0,那显然我们无法采药

       else if (j<t[i]) ans=dfs(i-1,j); //当我们取这个数时,要考虑这个数是不是大于剩余时间,这样也就避免了下一句中负数的出现

       else ans=max(dfs(i-1,j),dfs(i-1,j-t[i])+v[i]);//dfs核心语句

       vis[i][j]=ans;//标记

       return ans;

}

int main()

{

       cin>>T>>m;

       memset(vis,-1,sizeof(vis));

       for (int i=1;i<=m;i++) cin>>t[i]>>v[i];

       cout<<dfs(m,T);

}

第二题(最长上升子序列)

评析:一维较简单的DP,基本思路就是我们看是从现在接着往后,还是从后往前找到当时最长的子序列后接着往下

#include<bits/stdc++.h>

using namespace std;

int n,ans;

int a[1000005],f[1000005];

int main()

{

       cin>>n;

       for(int i=1;i<=n;i++) cin>>a[i];

       f[1]=1;

       for(int i=2;i<=n;i++)

              for(int j=i-1;j>=0;j--)//从后往前找

                     if(a[i]>a[j])

                     {

                            f[i]=max(f[j]+1,f[i]);//比较从哪里往后接下去

                     }

       for(int i=1;i<=n;i++) ans=max(ans,f[i]);//比对答案

       cout<<ans;

       return 0;

}

第三题(最大子段和)

评析:就是用一个sum记录当前前缀和,如果前缀和sum变成了负数,那么说明前面太小了,我们就从这个数开始,这时把sum置为0,再继续累加。

#include<bits/stdc++.h>

using namespace std;

int n,a,sum,ans=-10000;

int main()

{

   cin>>n;

   for(int i=1;i<=n;i++)

   {

       cin>>a;

       if(i==1) sum=a;

       else sum=max(a,sum+a);

       ans=max(ans,sum);

   }

   cout<<ans;

   return 0;

}

第四题

评析:LCS模板+双指针追踪,输出路径

#include<bits/stdc++.h>

using namespace std;

char s[3005],t[3005],ans[3005];

int n,m,f[3005][3005];

int main()

{

    scanf("%s",s+1);

       scanf("%s",t+1);//小操作,可以让输入的字符串从1开始,操作比较方便

       n=strlen(s+1);

       m=strlen(t+1);

       for (int i=1;i<=n;i++)

        for (int j=1;j<=m;j++)

        {

             f[i][j]=max(f[i-1][j],f[i][j-1]);

             if (s[i]==t[j]) f[i][j]=max(f[i][j],f[i-1][j-1]+1);

        }//LCS板子

        int i=n, j=m;//双指针

        while(f[i][j] > 0)

    {

              if(s[i]==t[j])

        {

            ans[f[i][j]] = s[i];//记录重复的

            i--;

                     j--;

        }

              else

        {

                     if(f[i][j]==f[i - 1][j]) i--;

                     else j--;

              }

       }

       printf("%s", ans+1);

    return 0;

}

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值