DP小小总结

先贴上题目练习
密码20210401

DP之旅开始了~

A
基础方程:dp[i][j]=max(dp[i-1][j-1],dp[i-1][j])+a[i][j];
这样是考虑[i][j]位置可由哪个位置过来
B
巨巨巨坑!看题容易漏条件:
如果当前格子是(x,y),下一步可以是(x+1,y),(x,y+1)或者(x,y*k)其中k>1。

/*
前提dp[i][j]=-inf;定义所有为负值
因为现在考虑是[i][j]可以到哪里,到的位置初始值-inf;
*/
dp[1][1]=a[1][1];
for(int i=1;i<=n;i++)
{
   	for(int j=1;j<=m;j++)
    {
    	dp[i+1][j]=max(dp[i+1][j],dp[i][j]+a[i+1][j]);
    	dp[i][j+1]=max(dp[i][j+1],dp[i][j]+a[i][j+1]);
    	for(int k=2;k*j<=m;k++)//每次循环求k倍
    	{
    		dp[i][j*k]=max(dp[i][j*k],dp[i][j]+a[i][j*k]);
		}
	}
}

D 最长上升子序列

//dp[i]=1;最初每个对应1;
for(int i=1;i<=n;i++)
{
    for(int j=1;j<=i;j++)
   	{
    	if(a[j]<a[i])
    		dp[i]=max(dp[i],dp[j]+1);
	}
}

F
题意:n行人,身高先增后减,最少挑出去多少人
思路:正反向最大递增序列or貌似正向递增+递减最大值也可
1.a[]正存,b[]逆存,dp1[]正增,dp2[]逆增
n-max(dp1[i]+dp2[i])-1;//-1 中间最高的算了两遍
os:不想贴代码了,把D正反鞭尸就行

G 最少拦截系统
题意:导弹拦截系统:它的第一发炮弹能够到达任意的高度,但是以后每一发炮弹都不能超过前一发的高度.
面对导弹,最少搞几套导弹拦截系统。
思路:

int main()
{
    int n;
    while(cin>>n)
    {
    	memset(a,0,sizeof(a));
    	memset(dp1,0,sizeof(dp1));
    	for(int i=1;i<=n;i++)
    		cin>>a[i];
		dp1[1]=a[1];
		int num=1;
		for(int i=1;i<=n;i++)
    	{
			int j;
    		for( j=1;j<=i;j++)
    		{
    			if(a[i]<=dp1[j])
    			{
    				dp1[j]=a[i];
    				break;
				}
			}
			if(j>i)
				dp1[++num]=a[i];
		}
		cout<<num<<'\n';
	}
    return 0;
}

H 最大上升子序列和

for(int i=1;i<=n;i++)
{
	dp[i]=a[i];
	for(int j=1;j<i;j++)
	{
		if(a[j]<a[i])
		dp[i]=max(dp[j]+a[i],dp[i]);
	}
}
int maxx=0;
for(int i=1;i<=n;i++)
{
	maxx=max(maxx,dp[i]);
}
printf("%d\n",maxx);

I

J 最大连续子序列和
推荐指数:***
题意:给一组数,全小于零输出0,else 求最大连续子序列和,并输出该子序列头尾元素。
我相信聪明的你可以看懂代码
os:我不想写了 等我下周码上

#include <cstdio>
#include <iostream>
#include <algorithm>
#include <string.h>
using namespace std;
typedef long long ll;
int a[10010];
int dp[10010];
int start[10010];
int endd[10010];
int max(int x,int y)
{
	if(x>y)return x;
	else return y;
}
int main()
{
	int n;
    while(~scanf("%d", &n)&&n)
    {
    	memset(a,0,sizeof(a));
    	memset(dp,0,sizeof(dp));
    	memset(start,0,sizeof(start));
    	memset(endd,0,sizeof(endd));
    	int f=0;
    	for(int i=1;i<=n;i++)
    	{
    		scanf("%d",&a[i]);
    		if(a[i]>=0)f=1;
		}
		if(f==0)
		{
			printf("0 %d %d\n",a[1],a[n]);
			continue;
		}
		int num1=1;
		int num2=1;
		dp[0]=-1;
		for(int i=1;i<=n;i++)
		{
			dp[i]=max(a[i],dp[i-1]+a[i]);
			if(dp[i-1]+a[i]<a[i])
			{
				start[num1]=a[i];
				endd[num2]=a[i];
			}
			else 
			{
				start[num1]=start[num1-1];
				endd[num2]=a[i];
			}	
			num1++;
			num2++;
		}
		int ff;
		int maxx=-1;
		for(int i=1;i<=n;i++)
		{
			if(maxx<dp[i])
			{
				maxx=dp[i];
				ff=i;
			}
		}
		printf("%d %d %d\n",maxx,start[ff],endd[ff]);	
    }
    return 0;
}

K bfs

上一篇:splay区间操作(bzoj1500)


下一篇:codeforces 上的小题