luogu2331
Posted gaojunonly1
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了luogu2331相关的知识,希望对你有一定的参考价值。
P2331 [SCOI2005]最大子矩阵
题目描述
这里有一个n*m的矩阵,请你选出其中k个子矩阵,使得这个k个子矩阵分值之和最大。注意:选出的k个子矩阵不能相互重叠。
输入格式
第一行为n,m,k(1≤n≤100,1≤m≤2,1≤k≤10),接下来n行描述矩阵每行中的每个元素的分值(每个元素的分值的绝对值不超过32767)。
输出格式
只有一行为k个子矩阵分值之和最大为多少。
输入输出样例
输入 #1
3 2 2
1 -3
2 3
-2 3
输出 #1
View Code
9
sol:dp[i][j][k]表示第一行匹配到i,第二行匹配到j,用了k个矩阵的最大值,XJB转移即可
#include <bits/stdc++.h> using namespace std; typedef int ll; inline ll read() ll s=0; bool f=0; char ch=‘ ‘; while(!isdigit(ch)) f|=(ch==‘-‘); ch=getchar(); while(isdigit(ch)) s=(s<<3)+(s<<1)+(ch^48); ch=getchar(); return (f)?(-s):(s); #define R(x) x=read() inline void write(ll x) if(x<0) putchar(‘-‘); x=-x; if(x<10) putchar(x+‘0‘); return; write(x/10); putchar((x%10)+‘0‘); #define W(x) write(x),putchar(‘ ‘) #define Wl(x) write(x),putchar(‘\n‘) const int N=105,M=15,inf=0x3f3f3f3f; int n,m,c,ans=-inf; int a[N][3],S[4][N],st[4][N][11]; int dp[N][N][M]; inline int cmin(int o,int a,int b) return (S[o][a]<S[o][b])?a:b; inline int ask(int o,int l,int r) int oo=log2(r-l+1); return cmin(o,st[o][l][oo],st[o][r-(1<<oo)+1][oo]); inline void Solve() int i,j,k; memset(dp,-63,sizeof dp); dp[0][0][0]=0; for(i=1;i<=n;i++) for(j=1;j<=c;j++) for(k=0;k<=i-1;k++) dp[i][0][j]=max(dp[i][0][j],dp[k][0][j-1]+S[1][i]-S[1][ask(1,k,i-1)]); dp[i][0][j]=max(dp[i][0][j],dp[k][0][j]); for(i=1;i<=n;i++) ans=max(ans,dp[i][0][c]); Wl(ans); int main() freopen("data.in","r",stdin); int i,j,k,l; R(n); R(m); R(c); S[1][0]=S[2][0]=S[3][0]=0; for(i=1;i<=n;i++) S[m+1][i]=S[m+1][i-1]; for(j=1;j<=m;j++) S[j][i]=S[j][i-1]+(a[i][j]=read()); S[m+1][i]+=a[i][j]; for(k=1;k<=m+1;k++) for(j=0;j<=n;j++) st[k][j][0]=j; for(i=1;i<=7;i++) for(j=0;j+(1<<i)-1<=n;j++) st[k][j][i]=cmin(k,st[k][j][i-1],st[k][j+(1<<(i-1))][i-1]); if(m==1) Solve(); return 0; // for(i=0;i<=n;i++) cout<<S[1][i]<<‘ ‘<<S[2][i]<<‘ ‘<<S[3][i]<<endl; // for(i=0;i<=n;i++) for(j=i;j<=n;j++) // // cout<<i<<" "<<j<<":"<<S[1][ask(1,i,j)]<<" "<<S[2][ask(2,i,j)]<<" "<<S[3][ask(3,i,j)]<<endl; // memset(dp,-63,sizeof dp); dp[0][0][0]=0; for(i=0;i<=n;i++) for(j=0;j<=n;j++) for(k=1;k<=c;k++) if(i==0&&j==0) continue; for(l=0;l<=i-1;l++) dp[i][j][k]=max(dp[i][j][k],dp[l][j][k-1]+S[1][i]-S[1][ask(1,l,i-1)]); dp[i][j][k]=max(dp[i][j][k],dp[l][j][k]); for(l=0;l<=j-1;l++) dp[i][j][k]=max(dp[i][j][k],dp[i][l][k-1]+S[2][j]-S[2][ask(2,l,j-1)]); dp[i][j][k]=max(dp[i][j][k],dp[i][l][k]); if(i==j) for(l=0;l<=i-1;l++) dp[i][j][k]=max(dp[i][j][k],dp[l][l][k-1]+S[3][i]-S[3][ask(3,l,i-1)]); dp[i][j][k]=max(dp[i][j][k],dp[l][l][k]); // cout<<dp[1][1][1]<<‘ ‘<<dp[2][2][1]<<‘ ‘<<dp[2][2][2]<<‘ ‘<<dp[3][3][2]<<endl; for(i=1;i<=n;i++) for(j=1;j<=n;j++) ans=max(ans,dp[i][j][c]); Wl(ans); return 0;
以上是关于luogu2331的主要内容,如果未能解决你的问题,请参考以下文章
(luogu题解搬运系列)luogu p2651 添加括号Ⅲ
(luogu题解搬运系列)luogu p1459 三值的排序