题目题意:
小L有两个长度均为n的数组 a,b以及初始值为0的x。小L现在能操作n次,每一次可以在以下两个规则中任选一个来更新x的值。规则一:将x更新为max(0,x-a[i]);规则二:将x更新为x^b[i]。计算在操作n次后,x的最大值。
题目知识点:
动态规划
题目分析:
每一次操作都是从规则一、二任选其一,且a、b两数组中的值都是不大于2047的。规则一显而易见,不论操作几次规则一,x的值都不可能大于2047;规则二由按位异或操作可知,不论操作几次规则二,x的值最小为0,最大为2047。综上所述,x的值的范围为[0,2047],既然如此,我们就可以用一个二维数组dp,i用来表示操作到的次数,j用来表示x可能的值。只要dp[i-1][j]为1,那么dp[i][max(0,j-a[i]]=1,dp[i][j^b[i]]=1,那么在操作完之后,我们就可以倒着遍历一遍最后操作,即dp[n][j],只要找到一个不为0的数,那么就可以输出并返回。
有了这样一个思路,我们就可以去写代码了:
#include<bits/stdc++.h>
using namespace std;
int a[2050];
int b[2050];
int dp[2050][2050]={0};
void solve(){
int n,x=0;
cin>>n;
for(int i=1;i<=n;i++) cin>>a[i];
for(int i=1;i<=n;i++) cin>>b[i];
dp[1][max(0,x-a[1])]=1; //第一次操作采用规则一的值
dp[1][x^b[1]]=1; //第一次操作采用规则二的值
//从第二次操作开始
for(int i=2;i<=n;i++){
for(int j=0;j<=2047;j++){
//如果对应j的前一项不为0,那么对应j的规则一、二均有可能取到
if(dp[i-1][j]){
dp[i][max(0,j-a[i])]=1;
dp[i][j^b[i]]=1;
}
}
}
//从后往前遍历,只要找到一个不为0的数,即为最大值
for(int j=2047;j>=0;j--){
if(dp[n][j]){
cout<<j;
return;
}
}
}
int main(){
solve();
}

京公网安备 11010502036488号