首页 > 其他分享 >P1437 [HNOI2004] 敲砖块 题解

P1437 [HNOI2004] 敲砖块 题解

时间:2024-10-07 21:22:51浏览次数:1  
标签:前缀 int 题解 51 P1437 HNOI2004 要取 三角形 dp

初拿到手感觉限制太多了,不好硬做,于是开始观察。
若要取某一个数,我们要取其左上右上两个数,而这两个数又要取上面三个数,所以取一个数的前提条件其实是取这一个三角形。
举例

2 2 3 4 5
8 2 7 12
2 3 6
4 9
3

比如我要取第3行的6,我首先要取7和12,要取7和12,首先要取3,4,5,所以一层层拓展下去形成一个与整个形状相似的三角形。
形式化总结一下,如果我要取 \(i,j\), 那么我要取以其为顶点的三角形,即 \(i-1,j\) 和 \(i-1,j+1\) \(etc\)。
所以自然想到做一个前缀和,表示这一个三角形的权值和,然后问题转化成了取哪些点能让我们的和最大。
考虑我选点不是无限制的,是 \(m\) 次,所以我设 \(dp_{i,j,k}\) 表示选到第 \(i\) 行第 \(j\) 列,还剩 \(k\) 次的最大和。
当前点所代表的三角形内数的个数是等差数列求和,即 \(\frac{(i+1) \times i}{2}\) 个数,选这个点就要选这些数。
而如果选的另外的点有重复,还要减去这些重复的点和权值,设这些点的数量为 \(num\) ,和为 \(sum\) ,\(i,j\) 的前缀和为 \(a_{i,j}\)
那么有状态转移方程(\(LaTeX\)太麻烦了qaq):

if(k>(i+1)*i/2-num) dp[i][j][k]=max(dp[i][j][k],dp[i][j][k-(i+1)*i/2+num]+a[i][j]-sum);

这是最直接的办法,然而我们根本不知道哪里重复了。
所以我们尝试对图形进行进一步的抽象总结。
我们看到多个三角形叠起来会形成一些折线,如图。
再把图搞优美一点 还是很丑qaq

7 \4 \5 3/ 2/ 4 5
 1 \3 \6/ 7/ 3 4
  5 \8/ \7/ 3 1
   2 5 7 3
    6 9 2
     2 3
      9

去掉重复则是

7 \4  5 3  2/ 4 5
 1 \3  6  7/ 3 4
  5 \8/ \7/ 3 1
   2 5 7 3
    6 9 2
     2 3
      9

我们发现这其实就转化成了一个用给定数量的线段围出一段波浪形,要使这一段的值最大的问题。那么我们的转移显然跟当前取的坐标、取到了第几个有关,所以我们可以设计三维 \(dp_{i,j,k}\) ,显然每次通过上一次转移只能从上面和左下,上面是没有意义的,只考虑左下。
然后我们考虑那个前缀和现在要转化成什么,当前考虑到第 \(i\) 行第 \(j\) 列,则第 \(j\) 列我打掉了的砖块是 \(1 \sim i-1\) ,所以对行做前缀和 。
则有 \(dp_{i,j,k}=max(dp_{i,j,k},dp_{l,j-1,k-i}+a_{i,j})\) 。
注意:
1.只在第一行统计答案,避免不合法。
2.先枚举列再枚举行,否则会造成左下的转移没有值。
3.初始值为 \(dp_{0,0,0}=0\),其他设成负无穷,避免不合法转移。
4.各种变量的范围,行可以不取,即可以为0,列不行。
5.l枚举转折点。

#include<bits/stdc++.h>
using namespace std;
int n,m,a[51][51],b[51][51];
long long dp[52][52][1280],maxi;
int main(){
	scanf("%d %d",&n,&m);
	for(int i=1;i<=n;++i){
		for(int j=1;j<=n-i+1;++j){
			scanf("%d",&b[i][j]);
			a[i][j]=a[i-1][j]+b[i][j];
		}
	}
	memset(dp,-0x3f,sizeof(dp));
	dp[0][0][0]=0;
	for(int j=1;j<=n;++j){
		for(int i=0;i+j<=n+1;++i){
			for(int l=0;l<=i+1;++l){
				for(int k=0;k<=m;++k){
					if(k>=i) dp[i][j][k]=max(dp[i][j][k],dp[l][j-1][k-i]+a[i][j]);
				}
			}
		}
	}
	for(int i=1;i<=n;++i) maxi=max(dp[1][i][m],maxi); 
	printf("%lld",maxi);
	return 0;
}

至此问题得以解决,时间复杂度 \(O(n^3m)\)。
其实还可以优化,但是我懒

标签:前缀,int,题解,51,P1437,HNOI2004,要取,三角形,dp
From: https://www.cnblogs.com/mountzhu/p/18448558

相关文章

  • 鲁的女孩 题解
    题意给两个数列,对它进行排列,使得对应两数的和的最大值最小。题解贪心,先将\(a\)、\(b\)排个序(先不考虑时间)。将\(a_1\)与\(a_n\)匹配。\(a_2\)与\(a_{n-1}\)匹配。……取最大值即可。考虑到\(n\le10^5\),不可以暴力枚举。但是\(a,b\le100\),可以开一个桶,......
  • 题解 QOJ1869【Power Station of Art】/ SS241006B【结论题】
    题解QOJ1869【PowerStationofArt】/SS241006B【结论题】PetrozavodskSummer2021.Day6.XJTUContest,GPofXJTUXXIIOpenCupnamedafterE.V.Pankratiev,GrandPrixofXi'an题目描述给出一个无向图,每个点有点权\(a\)和颜色\(c\),其中颜色只会有红蓝两种。......
  • CF131C题解
    传送门:https://codeforces.com/problemset/problem/134/C关注到题目的两个限制:1.一个人只能与另外同一人交换一张卡牌。2.一个人只能交换自己原来颜色的卡牌。对于2条限制条件,显然有贪心思路:尽量让更多的人手持原有的卡牌。对于当前待交换的卡牌,一种构造思路,我们每次贪心选取......
  • 伊吹萃香 题解
    题意(很复杂,真的不想概括,以下是原题面)在幻想乡,伊吹萃香是能够控制物体密度的鬼王。因为能够控制密度,所以萃香能够制造白洞和黑洞,并可以随时改变它们。某一天萃香闲着无聊,在妖怪之山上设置了一些白洞或黑洞,由于引力的影响,给妖怪们带来了很大的麻烦。于是他们决定找出一条消耗体力......
  • CF1117E Decypher the String题解
    传送门神奇的题。这是一道交互题。给定一个字符串\(s\),我们拥有若干操作,但是你不知道,第\(i\)个操作形如\(a_i,b_i\)表示交换字符串\(s\)中的第\(a_i\)位和\(a_j\)位。比如操作序列依次为\((1,2),(2,3)\),给定字符串为xyz。那么我们执行第一次操作后......
  • 题解 QOJ2559【Endless Road】/ SS241006D【套路题】
    PetrozavodskWinter2022.Day2.KAISTContest+KOITST2021XXIIOpenCupnamedafterE.V.Pankratiev,GrandPrixofDaejeon题目描述现在有\(10^9\)个花盆,依次编号为\(1,2,\dots,10^{9}\)。给定\(n\)个二元组\(L_i,R_i(L_i<R_i)\),我们将进行\(n\)次以下操......
  • CF722F Cyclic Cipher 题解
    传送门给定\(n\)个数列,第\(i\)个数列包含\(k_i\)个不超过\(m\)的互不相同的正整数(从\(1\)开始标号)。每一秒将每个数列中的数左移一个位置(即将每个数的下标\(-1\),下标\(1\)的数下标变为\(k_i\)),并记录由每个数列的第一个数组成的序列。\(10^{100}\)秒过......
  • [NOIP2023] 双序列拓展 题解
    qaq首先我们考虑其实这个条件就是要满足\(f\)严格比\(g\)大或\(f\)严格比\(g\)小。在这里只讨论大于。然后考虑到对于一个\(i\)如果不满足,我们可以把对应数组向右移一位看是否满足,如果还是不满足就无解了。考虑对于现在满足的\(i\),我们可以分别把两个指针向右移一......
  • EGOI2024 简单题解
    Day1T1InfiniteRace由于只有重复超过一个人才肯定是跑过一圈的,所以只用用一个数组做标记就可以了,每超过一次就打上标记,否则去掉标记。T2Bouquet定义\(dp[i]\)为,以第\(i\)种郁金香结尾的选法中最大可选的郁金香数量,易得状态转移方程为:\(dp[i]=max{dep[j]}+1(j<l_i\le......
  • mysql登录遇到ERROR 1045问题解决方法
    遇到MySQL登录时出现 ERROR1045(访问被拒绝,用户名或密码错误),可以通过以下步骤来解决:1.确认用户名和密码检查用户名和密码:确认在连接数据库时输入的用户名和密码是否正确。尝试在命令行中连接数据库,确认是否能成功登录:bash mysql-uyour_username-p2.重......