1573 分离与合体(LOJ10151) 区间动规 区间动规合并过程

总目录

在线测评地址(ybt)

在线测评地址(LOJ)

1.区间动规 区间动规合并过程

ybt

通过

测试点 结果 内存 时间
测试点1 答案正确 1708KB 8MS
测试点2 答案正确 628KB 2MS
测试点3 答案正确 656KB 2MS
测试点4 答案正确 764KB 2MS
测试点5 答案正确 788KB 2MS
测试点6 答案正确 1148KB 2MS
测试点7 答案正确 1388KB 4MS
测试点8 答案正确 1640KB 7MS
测试点9 答案正确 1704KB 8MS
测试点10 答案正确 1708KB 8MS

LOJ

1573 分离与合体(LOJ10151) 区间动规 区间动规合并过程 题意挺玄乎,弄懂样例是关键。

7
1 2 3 4 5 6 7

dp[1][2]=(1+2)*1=2
dp[2][3]=(2+3)*2=10
dp[3][4]=(3+4)*3=21
dp[4][5]=(4+5)*4=36
dp[5][6]=(5+6)*5=55
dp[6][7]=(6+7)*6=78

dp[1][3]=max(dp[2][3]+(1+3)*1,dp[1][2]+(1+3)*2)=max(14,10)=14
dp[2][4]=max(dp[3][4]+(2+4)*2,dp[2][3]+(2+4)*3)=max(33,28)=33
dp[3][5]=max(dp[4][5]+(3+5)*3,dp[3][4]+(3+5)*4)=max(60,53)=60
dp[4][6]=max(dp[5][6]+(4+6)*4,dp[4][5]+(4+6)*5)=max(95,86)=95
dp[5][7]=max(dp[6][7]+(5+7)*5,dp[5][6]+(5+7)*6)=max(138,127)=138

dp[1][4]=max(dp[2][4]+(1+4)*1,dp[1][2]+dp[3][4]+(1+4)*2,dp[1][3]+(1+4)*3)=max(38,33,29)=38
dp[2][5]=max(dp[3][5]+(2+5)*)
dp[3][6]=
dp[4][7]=

dp[1][5]=
dp[2][6]=
dp[3][7]=

dp[1][6]=
dp[2][7]=

dp[1][7]=

实在写不下去了,编码吧,先看看最大值是否能核上。

核验最值及中间过程的代码如下:

#include <bits/stdc++.h>
#define maxn 310
using namespace std;
unsigned int a[maxn],dp[maxn][maxn];
int main(){
	int n,lt,rt,k,i,len;
	scanf("%d",&n);
	for(i=1;i<=n;i++)scanf("%u",&a[i]);
	for(len=1;len<=n-1;len++)
		for(lt=1;lt<=n;lt++){
			rt=lt+len;
			if(rt>n)break;
			for(k=0;k<len;k++)
				dp[lt][rt]=max(dp[lt][rt],dp[lt][lt+k]+dp[lt+k+1][rt]+(a[lt]+a[rt])*a[lt+k]);
			printf("dp[%d][%d]=%u\n",lt,rt,dp[lt][rt]);
		}
	printf("%u\n",dp[1][n]);
	return 0;
}

上述代码对应的输入输出数据如下:

7
1 2 3 4 5 6 7

dp[1][2]=3
dp[2][3]=10
dp[3][4]=21
dp[4][5]=36
dp[5][6]=55
dp[6][7]=78
dp[1][3]=14
dp[2][4]=33
dp[3][5]=60
dp[4][6]=95
dp[5][7]=138
dp[1][4]=38
dp[2][5]=74
dp[3][6]=122
dp[4][7]=182
dp[1][5]=80
dp[2][6]=138
dp[3][7]=212
dp[1][6]=145
dp[2][7]=230
dp[1][7]=238
238

该题需要记录区间合并过程。

打印区域犯难了,再仔细读题,发现,还是对打印区域进行了具体说明:

例如先打印一分为二的区域,然后从左到右打印二分为四的分离区域,然后是四分为八的……

样例对应的分裂过程如下:

b[1][7]
b[1][1] b[2][7] 输出1
b[1][1] b[2][2] b[3][7] 输出2
b[1][1] b[2][2] b[3][3] b[4][7] 输出3
b[1][1] b[2][2] b[3][3] b[4][4] b[5][7] 输出4
b[1][1] b[2][2] b[3][3] b[4][4] b[5][5] b[6][7] 输出5
b[1][1] b[2][2] b[3][3] b[4][4] b[5][5] b[6][6] b[7][7] 输出6

分裂的输出还是比较考验思维的。

基本思路:记录区间动规过程,一遍一遍的打印分裂位置,具体可见代码。

区间动规 区间动规合并过程 代码如下:

#include <bits/stdc++.h>
#define maxn 310
using namespace std;
unsigned int a[maxn],dp[maxn][maxn],b[maxn][maxn],vis[maxn];
int main(){
	int n,lt,rt,k,i,len;
	scanf("%d",&n);
	for(i=1;i<=n;i++)scanf("%u",&a[i]);
	for(len=1;len<=n-1;len++)
		for(lt=1;lt<=n;lt++){
			rt=lt+len;
			if(rt>n)break;
			for(k=0;k<len;k++)
				if(dp[lt][rt]<dp[lt][lt+k]+dp[lt+k+1][rt]+(a[lt]+a[rt])*a[lt+k]){
					dp[lt][rt]=dp[lt][lt+k]+dp[lt+k+1][rt]+(a[lt]+a[rt])*a[lt+k];
					b[lt][rt]=lt+k;
				}
		}
	printf("%u\n",dp[1][n]);
	int print=1;//打印分裂过程 
	vis[n]=1;//关键点
	while(print){
		print=0;
		lt=1;
		for(rt=1;rt<=n;rt++)
			if(vis[rt]){
				k=b[lt][rt];
				if(k){
					printf("%u ",k);
					vis[k]=1;
					print=1;
				}
				lt=rt+1;//关键点
			}
	} 
	printf("\n");
	return 0;
}

该题习得了什么?无符号整数的输入与输出。 %u

独立写出了区间动规的分裂过程。

上一篇:多校省选模拟4


下一篇:「CCO 2021」商旅