备战蓝桥杯---动态规划(应用1)

话不多说,直接看题:

备战蓝桥杯---动态规划(应用1)_第1张图片

首先我们考虑暴力,用二维前缀和即可,复杂度为o(n^4).

其实,我们不妨枚举任意2行,枚举以这个为边界的最大矩阵。

我们把其中的每一列前缀和维护出来,相当于把一个矩阵压缩成了一个序列,然后问题就转化为了求一个序列的最大子段和。

下面为AC代码:

#include
using namespace std;
int n,a[300][300],lie[300][300],b[300],hh[300];
int ck(){
	int ss=-0x3f3f3f3f;
	memset(hh,0,sizeof(hh));
	for(int i=1;i<=n;i++){
		hh[i]=max(b[i],b[i]+hh[i-1]);
		ss=max(ss,hh[i]);
	}
	return ss;
}
int main(){
	cin>>n;
	for(int i=1;i<=n;i++){
		for(int j=1;j<=n;j++){
			cin>>a[i][j];
			lie[i][j]=a[i][j]+lie[i-1][j];
		}
	}
	int ans=-0x3f3f3f3f;
	for(int i=1;i<=n;i++){
		for(int j=i+1;j<=n;j++){
			for(int k=1;k<=n;k++){
				b[k]=lie[j][k]-lie[i][k];
			}
			ans=max(ans,ck());
		}
	}
	cout<

扩展一下,假如是求立方体呢?

我们枚举两个x方向与y方向的线,然后在z轴上前缀和压缩即可,复杂度为o(n^5)

接题:

备战蓝桥杯---动态规划(应用1)_第2张图片

第一问就是求导弹的最长不上升子序列。

对于第二问当高度递增时,要打全部需要相应的个数,换句话说就是至少要导弹的最长上升子序列。

其实,这个数量刚刚可以,我们不妨用反证法,假如还需要一个,不妨假设它栏A与B(A

下面是AC代码:

#include
using namespace std;
int b,cnt,a[100010],dp1[100010],dp2[100010];
int main(){
    while(cin>>b){
        a[++cnt]=b;
    }
    for(int i=1;i<=cnt;i++){
        dp1[i]=1;
        for(int j=1;j=a[i]){
                dp1[i]=max(dp1[i],1+dp1[j]);
            }
        }
    }
    int ans=1;
    for(int i=1;i<=cnt;i++){
        ans=max(ans,dp1[i]);
    }
    cout<

备战蓝桥杯---动态规划(应用1)_第3张图片

我们不妨设f[i][0]表示上升的最大长度(i必选),f[i][1]表示先上升在下降的最大长度(i必选)

于是我们得到转移方程f[i][0]=max(1+f[k][0]),f[i][1]=max(f[k][0]+1,f[k][1]+1)

下面是AC代码:

#include
using namespace std;
int b,cnt,a[100010],dp1[100010],dp2[100010];
int main(){
    while(cin>>b){
        a[++cnt]=b;
    }
    for(int i=1;i<=cnt;i++){
        dp1[i]=1;
        for(int j=1;j=a[i]){
                dp1[i]=max(dp1[i],1+dp1[j]);
            }
        }
    }
    int ans=1;
    for(int i=1;i<=cnt;i++){
        ans=max(ans,dp1[i]);
    }
    cout<

接题:

备战蓝桥杯---动态规划(应用1)_第4张图片

我们换一次需要用一次次数得到下-上的值,容易与想到与背包问题类似。

于是我们类比定义:f[i][j]为前i个骨牌得到j的最小次数。

易得转移方程:f[i][j]=min(f[i-1][j-(上-下)],f[i-1][j+(上-下)]+1)

有俩个细节:1.对于初值我们赋值为正无穷。

2.对于负数问题,我们平移处理。

下面是AC代码:

#include
using namespace std;
#define ck 5001
int n,dp[2][10010];
struct node{
	int shang,xia;
}a[1010];
int main(){
	cin>>n;
	for(int i=1;i<=n;i++) scanf("%d%d",&a[i].shang,&a[i].xia);
	memset(dp,0x3f,sizeof(dp));
	dp[0][0+ck]=0;
	for(int i=1;i<=n;i++){
		for(int j=-5*i+ck;j<=5*i+ck;j++){
			int hh=a[i].shang-a[i].xia;
			dp[i%2][j]=min(dp[(i-1)%2][j-hh],dp[(i-1)%2][j+hh]+1);
		}
	}
	int mm=ck;
	if(dp[n%2][ck]<=n) cout<=0;i--){
			if(dp[n%2][i]<=n) break;
		}
		for(;j<=10009;j++){
			if(dp[n%2][j]<=n) break;
		}
		if(i+j==2*ck) cout<2*ck) cout<

你可能感兴趣的:(蓝桥杯,动态规划,算法,c++,背包问题)