洛谷 P5144 蜈蚣

题目描述

分析

首先我们得知道什么是异或,这道题的核心就在于看到异或进行转移。

异或xor,^,A xor B就是再A,B两个数的二进制数中相同为0,不同为1。
一些定理: 0 x o r A = A ; 0 xor A = A; 0xorA=A; A x o r A = 0 ; A xor A = 0; AxorA=0; A x o r ( B x o r C ) = ( A x o r B ) x o r C ; A xor (B xor C) = (A xor B) xor C; Axor(BxorC)=(AxorB)xorC;
因为这道题是的蜈蚣是一节一节的,并且是要求蜈蚣分为m段再异或后的最大值,不难想到设Dp[i][j]表示前i节蜈蚣分为j段能获得的最大值。让后我们可以利用xor的交换律对这个进行转移。 d p [ i ] [ j ] = m a x ( d p [ i ] [ j ] , d p [ i ] [ k ] + S u m X o r ( i , k ) ) dp[i][j] = max(dp[i][j],dp[i][k] + SumXor(i,k)) dp[i][j]=max(dp[i][j],dp[i][k]+SumXor(i,k))
其中SumXor表示从i到k所有值异或起来的总和,我们可以设一个前缀和来表示前i个的异或总值,让后面DP时不用再一个一个地去求,以防T掉。dp的初始状态是dp[i][1] = sum[i],因为dp[i][1]就表示了i段分为1组的最大值,显然是他异或起来的本身,因为我们要求n段分为m组的最大值,所以说答案存在是dp[n][m].
十分简洁的的代码:

#include <cstdio>
#include <algorithm>
using namespace std;
const int MAXN = 1e3 + 5;
int n,m,w[MAXN],s[MAXN],dp[MAXN][MAXN];
int main() {
	scanf("%d %d",&n,&m);
	for(int i = 1;i <= n;i ++) {
		scanf("%d",&w[i]);
		s[i] = s[i - 1] ^ w[i];
	}
	for(int i = 1;i <= n;i ++) dp[i][1] = s[i];
	for(int j = 2;j <= m;j ++)
	for(int k = 1;k <= n;k ++)
	for(int i = k;i <= n;i ++)
	dp[i][j] = max(dp[i][j],dp[k][j - 1] + (s[i] ^ s[k]));
	printf("%d",dp[n][m]);
	return 0;
}

END

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值