【HZNU Summer training】XOR-pyramid(DP)

    此题的题意大致是说,给出一个数组,并定义一个运算f(b),这个运算在参数个数大于1时递归地计算相邻参数两两异或的结果,每次迭代都会减少一个参数。题目要求求解这串数组中任意一个片段通过f(b)运算获得的最大结果。

    由此看出,异或在此题中只是作为一个运算符使用的,不需要我们去理解。那么这题就被转化为类似与数塔问题的基础DP问题。但要注意的一点是,数塔问题是对于整个数组求最优解,此题要求的是“任一片段的最优解”,因此在自底向上做完状态转移后,还需遍历一遍得到的二维数组,将dp[i][j]更新为dp[i][j],dp[i-1][j],dp[i-1][j+1]中的最大值(因为DP的最优子结构性质,dp数组中的每个元素都代表了当前片段的最优解,因此只用将整个数组的最优解继承到顶部即可)。

AC代码如下: 

#include<iostream>
#include<set>
#include<utility>
#include<map>
#include<algorithm>
#include<queue>
#include<cstring>
#include<string>
#include<vector>
#include<cstdio>
#include<cmath>
#define INF 0x3f3f3f3f
using namespace std;
long long dp[5050][5050],a[5050];
long long maxx(long long a,long long b,long long c){
	return a>max(b,c)?a:max(b,c);
}
int main() {
	long long n;
	while(cin>>n){
		memset(dp,0,sizeof(dp));
		memset(a,0,sizeof(a));
		long long q;
		for(int i=0;i<n;i++){
			cin>>a[i];
			dp[0][i]=a[i];
		} 
		for(int i=1;i<n;i++){
			for(int  j=0;j<n-i;j++){
				dp[i][j]=dp[i-1][j]^dp[i-1][j+1];
			}
		}
		for(int i=1;i<n;i++){
			for(int j=0;j<n-i;j++){
				dp[i][j]=maxx(dp[i][j],dp[i-1][j],dp[i-1][j+1]);
			}
		}

//		for(int i=0;i<n;i++){
//			cout<<"*";
//			for(int j=0;j<n-i;j++){
//				printf("%2d ",dp[i][j]); 这一段代码用于输出整个数组,方便调试
//			}
//			cout<<endl;
//		}

		long long l,r;
		cin>>q;
		for(int i=0;i<q;i++){
			cin>>l>>r;
			cout<<dp[r-l][l-1]<<endl;
		}		
	}
	return 0;
}

    需要注意的是,若使用自底向上方法,最后取用数组中元素的时候,需要对下标做一下变化,这里可以在草稿纸上先写出结果再做分析,也可以直接先输出整个DP数组,用来分析。

猜你喜欢

转载自blog.csdn.net/linyiduo123/article/details/81109791
今日推荐