DP习题解题报告

由于是写个自己看的,题意就不放了
ProblemA

思路:
存数的数组 a[maxn]
先建立二维数组 dp[i][j] 含义:前j个数分i组所得最大值
在第j个数这,其选取有两种情况:(每种情况必须满足选后组份为i)
case 1 :已经有了i-1组 slove:将a[j]作为单独一组加入 ---->dp[i][j]=max(dp[i-1][k])+a[j] i-1<=k<=j-1

case 2 :已经有了i组 slove:将a[j]添加到前i组中的某一组 又由于区间连续性 因此只能添加到含有a[j-1]的那组 dp[i][j]=dp[i][j-1]+a[i]

综上 状态转移方程: dp[i][j]=max(dp[i][j-1],max(dp[i-1][k]))+a[j] i-1<=k<=j-1其中max(dp[i-1][k])可以用一数组记录

那么二维dp数组解的代码:

/*********************************************************************/
/**********************************cyf*******************************/
/*******************************************************************/
#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
#include<cmath>
#include<string>
#include<vector>
#include<set>
#include<map>
#include<queue>
#include<stack>
using namespace std;
#define rep(i,x) for(int i=0;i<x;i++)
#define ll long long
#define repp(i,x) for(int i=1;i<=x;i++)
#define repx(i,n,j) for(int i=j;i<n;i++)
#define rep(i,begin,end) for(int i=begin;i<=end;i++)
#define mst(a,b) memset(a,b,sizeof(a))
#define drep(i,a,b) for(int i=a;i>=b;i--)
const ll mod=1e9+7;
const int INF=0x3f3f3f3f;;
const int maxn=1e4+5;
ll a[maxn],dp[maxn][maxn],zj[maxn][maxn];
int main()
{
    int n,m;
    ll ans;
    while(cin>>m>>n)
    {
        rep(i,1,n)
        cin>>a[i];
        mst(dp,0);
        mst(zj,0);
        rep(i,1,m)
        {
            ans=-INF;
            rep(j,i,n)
            {
                dp[i][j]=max(dp[i][j-1],zj[i-1][j-1])+a[j];
                if(j>=i)
                zj[i][j]=max(zj[i][max(i,j-1)],dp[i][j]);
                if(i==m)
                    ans=max(dp[m][j],ans);
            }
        }
        cout<<ans<<endl;
    }
    return 0;
}

但是你的编译器会给你报错 数组开太大 因此我们要用滚动数组优化

/*********************************************************************/
/**********************************cyf*******************************/
/*******************************************************************/
#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
#include<cmath>
#include<string>
#include<vector>
#include<set>
#include<map>
#include<queue>
#include<stack>
using namespace std;
#define rep(i,x) for(int i=0;i<x;i++)
#define ll long long
#define repp(i,x) for(int i=1;i<=x;i++)
#define repx(i,n,j) for(int i=j;i<n;i++)
#define rep(i,begin,end) for(int i=begin;i<=end;i++)
#define mst(a,b) memset(a,b,sizeof(a))
#define drep(i,a,b) for(int i=a;i>=b;i--)
const ll mod=1e9+7;
const int INF=0x3f3f3f3f;;
const int maxn=1e6+5;
ll a[maxn];
ll dp[maxn];
ll zj[maxn];
int main()
{
	int n,m;
	ll ans;
	while (~scanf("%d %d",&m,&n))
	{
		rep(i,1,n)
		scanf("%lld",&a[i]);
		mst(dp,0);
		mst(zj,0);
		rep(i,1,m)
		{
			ans=-INF;
			rep(j,i,n)
			{
				dp[j]=max(dp[j-1]+a[j],zj[j-1]+a[j]);
				zj[j-1]=ans;
				ans=max(ans,dp[j]);
			}
		}
		printf("%lld\n",ans);
	}
	
    return 0;
}

pronlemB
这题感觉不是dp题,可能是我理解不够
一种O(n)写法:
可知至少出现(n+1)/2次,那么出现次数>数据的一半
定义一个计数变量 unt
case 1 unt==0 : unt=1 ans=a[i]
case 2 unt!=0: ans和a[i]比较 同unt++,不同unt–

/*********************************************************************/
/**********************************cyf*******************************/
/*******************************************************************/
#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
#include<cmath>
#include<string>
#include<vector>
#include<set>
#include<map>
#include<queue>
#include<stack>
using namespace std;
#define rep(i,x) for(int i=0;i<x;i++)
#define ll long long
#define repp(i,x) for(int i=1;i<=x;i++)
#define repx(i,n,j) for(int i=j;i<n;i++)
#define rep(i,begin,end) for(int i=begin;i<=end;i++)
#define mst(a,b) memset(a,b,sizeof(a))
#define drep(i,a,b) for(int i=a;i>=b;i--)
const ll mod=1e9+7;
const int INF=0x3f3f3f3f;;
const int maxn=1e6+5;
ll a[maxn];
ll dp[maxn];
ll zj[maxn];
int main()
{
	ll n;
	ll ans,unt,x;
	while (~scanf("%lld",&n))
	{
		unt=0;
		rep(i,1,n)
		{
			scanf("%lld",&x);
			if(unt==0)
			{
				unt++;
				ans=x;
			}
			else
			{
				if(ans==x)
				unt++;
				else
				{
					unt--;
				}
				
			}
			
		}
		printf("%lld\n",ans);
	}
	
    return 0;
}

problemC

这题因为码的时候一个手误差点把我人wa没了
最长递增子序列O(n^2)解法 另一种还没学
解法:
每一种石头长宽高按全排 最终共6*n总
长宽sort一遍
dp[i]就是以i快石头结尾最大高度
dp[i]=max(a[i].g,dp[k]) 这里1<=k<=i-1 && a[k]满足题目条件
结果就是dp数组最大值
(注释是dbug留下的产物)

/*********************************************************************/
/**********************************cyf*******************************/
/*******************************************************************/
#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
#include<cmath>
#include<string>
#include<vector>
#include<set>
#include<map>
#include<queue>
#include<stack>
using namespace std;
#define rep(i,x) for(int i=0;i<x;i++)
#define ll long long
#define repp(i,x) for(int i=1;i<=x;i++)
#define repx(i,n,j) for(int i=j;i<n;i++)
#define rep(i,begin,end) for(int i=begin;i<=end;i++)
#define mst(a,b) memset(a,b,sizeof(a))
#define drep(i,a,b) for(int i=a;i>=b;i--)
const ll mod=1e9+7;

const int INF=0x3f3f3f3f;;
const int maxn=1e3+5;
struct st
{
    ll c,k,g;
}a[maxn];
bool ccmmpp(struct st x,struct st y)
{
    if(x.c==y.c)
    {
        return x.k>y.k;
    }
    return x.c>y.c;
}
ll dp[maxn];
int main()
{
    int tt=0;
    ll n,ans;
    ll x,y,z,js=1;
    while(cin>>n && n!=0){
    tt++;
    js=1;
    rep(i,1,n)
    {
        cin>>x>>y>>z;
        a[js].c=x;
        a[js].k=y;
        a[js++].g=z;

        a[js].c=x;
        a[js].k=z;
        a[js++].g=y;

        a[js].c=y;
        a[js].k=x;
        a[js++].g=z;

        a[js].c=y;
        a[js].k=z;
        a[js++].g=x;

        a[js].c=z;
        a[js].k=x;
        a[js++].g=y;

        a[js].c=z;
        a[js].k=y;
        a[js++].g=x;
    }
    js--;
    /*cout<<js<<endl;*/
    n=js;
    /*rep(i,1,n)
    cout<<a[i].c<<" "<<a[i].k<<" "<<a[i].g<<endl;*/
    ans=0;
    mst(dp,0);
    sort(a+1,a+1+n,ccmmpp);
    rep(i,1,n)
    {
        /*cout<<i<<endl;*/
        ll t=0;
        rep(j,1,i-1)
        {
            /*cout<<j<<endl;*/
            if(a[j].c>a[i].c && a[j].k>a[i].k)
                t=max(t,dp[j]);
        }
        /*cout<<t<<endl;*/
        dp[i]=t+a[i].g;
        /*cout<<dp[i]<<endl;*/
        ans=max(ans,dp[i]);
    }
    /*cout<<tt<<" "<<ans<<endl;*/
    printf("Case %d: maximum height = %lld\n",tt,ans);
    /*cout<<"Case "<<tt<<": maximum height = ";
    cout<<ans<<endl;*/
    }
    return 0;
}

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
资源包主要包含以下内容: ASP项目源码:每个资源包中都包含完整的ASP项目源码,这些源码采用了经典的ASP技术开发,结构清晰、注释详细,帮助用户轻松理解整个项目的逻辑和实现方式。通过这些源码,用户可以学习到ASP的基本语法、服务器端脚本编写方法、数据库操作、用户权限管理等关键技术。 数据库设计文件:为了方便用户更好地理解系统的后台逻辑,每个项目中都附带了完整的数据库设计文件。这些文件通常包括数据库结构图、数据表设计文档,以及示例数据SQL脚本。用户可以通过这些文件快速搭建项目所需的数据库环境,并了解各个数据表之间的关系和作用。 详细的开发文档:每个资源包都附有详细的开发文档,文档内容包括项目背景介绍、功能模块说明、系统流程图、用户界面设计以及关键代码解析等。这些文档为用户提供了深入的学习材料,使得即便是从零开始的开发者也能逐步掌握项目开发的全过程。 项目演示与使用指南:为帮助用户更好地理解和使用这些ASP项目,每个资源包中都包含项目的演示文件和使用指南。演示文件通常以视频或图文形式展示项目的主要功能和操作流程,使用指南则详细说明了如何配置开发环境、部署项目以及常见问题的解决方法。 毕业设计参考:对于正在准备毕业设计的学生来说,这些资源包是绝佳的参考材料。每个项目不仅功能完善、结构清晰,还符合常见的毕业设计要求和标准。通过这些项目,学生可以学习到如何从零开始构建一个完整的Web系统,并积累丰富的项目经验。
资源包主要包含以下内容: ASP项目源码:每个资源包中都包含完整的ASP项目源码,这些源码采用了经典的ASP技术开发,结构清晰、注释详细,帮助用户轻松理解整个项目的逻辑和实现方式。通过这些源码,用户可以学习到ASP的基本语法、服务器端脚本编写方法、数据库操作、用户权限管理等关键技术。 数据库设计文件:为了方便用户更好地理解系统的后台逻辑,每个项目中都附带了完整的数据库设计文件。这些文件通常包括数据库结构图、数据表设计文档,以及示例数据SQL脚本。用户可以通过这些文件快速搭建项目所需的数据库环境,并了解各个数据表之间的关系和作用。 详细的开发文档:每个资源包都附有详细的开发文档,文档内容包括项目背景介绍、功能模块说明、系统流程图、用户界面设计以及关键代码解析等。这些文档为用户提供了深入的学习材料,使得即便是从零开始的开发者也能逐步掌握项目开发的全过程。 项目演示与使用指南:为帮助用户更好地理解和使用这些ASP项目,每个资源包中都包含项目的演示文件和使用指南。演示文件通常以视频或图文形式展示项目的主要功能和操作流程,使用指南则详细说明了如何配置开发环境、部署项目以及常见问题的解决方法。 毕业设计参考:对于正在准备毕业设计的学生来说,这些资源包是绝佳的参考材料。每个项目不仅功能完善、结构清晰,还符合常见的毕业设计要求和标准。通过这些项目,学生可以学习到如何从零开始构建一个完整的Web系统,并积累丰富的项目经验。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值