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
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
using namespace std;
#define rep(i,x) for(int i=0;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
#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
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
using namespace std;
#define rep(i,x) for(int i=0;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
#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
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
using namespace std;
#define rep(i,x) for(int i=0;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
#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
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
using namespace std;
#define rep(i,x) for(int i=0;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
#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<
    n=js;
    /*rep(i,1,n)
    cout<
    ans=0;
    mst(dp,0);
    sort(a+1,a+1+n,ccmmpp);
    rep(i,1,n)
    {
        /*cout<
        ll t=0;
        rep(j,1,i-1)
        {
            /*cout<
            if(a[j].c>a[i].c && a[j].k>a[i].k)
                t=max(t,dp[j]);
        }
        /*cout<
        dp[i]=t+a[i].g;
        /*cout<
        ans=max(ans,dp[i]);
    }
    /*cout<
    printf("Case %d: maximum height = %lld\n",tt,ans);
    /*cout<<"Case "<}
    return 0;
}

你可能感兴趣的:(动态规划)