专栏文章

题解:P1005 [NOIP 2007 提高组] 矩阵取数游戏

P1005题解参与者 8已保存评论 9

文章操作

快速查看文章及其快照的属性,并进行相关操作。

当前评论
9 条
当前快照
1 份
快照标识符
@miqac1j8
此快照首次捕获于
2025/12/04 01:32
3 个月前
此快照最后确认于
2025/12/04 01:32
3 个月前
查看原文
一道考试中的题,来写篇题解。
我们首先发现每行是独立的,于是可以一行一行的处理。
又发现贪心有后效性,遂准备 dp。
对于每行,设 dpl,rdp_{l,r} 为除了区间 [l,r][l,r],其它数都取完的最大得分。
所以这一行的最大得分为 max1xmdpx,x1\max_{1\le x\le m}dp_{x,x-1}
转移也很好想了,设 s=rl+1s=r-l+1aa 数组为该行的数字。
dpl,r=max(dpl1,r+al1×2ns,dpl,r+1+ar+1×2ns)dp_{l,r}=\max(dp_{l-1,r}+a_{l-1}\times 2^{n-s},dp_{l,r+1}+a_{r+1}\times 2^{n-s})
此式转移一个是取左边一个是取右边,所以显然成立。
最后就是注意 dpdp 的转移顺序了,还有要开 __int128
一道水绿就这样的切了。
CPP
#include<bits/stdc++.h>
using namespace std;
int n,m;
int a[110];
__int128 dp[110][110];
__int128 sum=0;
void write(__int128 x){
	if(x>=10) write(x/10);
	putchar(x%10+'0');
}
int main() {
	cin>>n>>m;
	for(int i=1;i<=n;i++){
		for(int j=1;j<=m;j++) cin>>a[j];
		dp[1][m]=0;
		for(int j=1;j<=m;j++)
			for(int k=m;k>=j-1;k--)
				dp[j][k]=max(dp[j-1][k]+a[j-1]*(__int128(1)<<(j-1+m-k)),dp[j][k+1]+a[k+1]*(__int128(1)<<(j-1+m-k)));
		__int128 ans=0;
		for(int j=1;j<=m;j++) ans=max(ans,dp[j][j-1]);
		sum+=ans;
	}
	write(sum);
	return 0;
}

评论

9 条评论,欢迎与作者交流。

正在加载评论...