bzoj1084 [SCOI2005]最大子矩陣
阿新 • • 發佈:2017-10-25
inline dp2 轉移 mat ace end char 相互 nbsp
1 -3
2 3
-2 3
Description
這裏有一個n*m的矩陣,請你選出其中k個子矩陣,使得這個k個子矩陣分值之和最大。註意:選出的k個子矩陣不能相互重疊。
Input
第一行為n,m,k(1≤n≤100,1≤m≤2,1≤k≤10),接下來n行描述矩陣每行中的每個元素的分值(每個元素的分值的絕對值不超過32767)。
Output
只有一行為k個子矩陣分值之和最大為多少。
Sample Input
3 2 21 -3
2 3
-2 3
Sample Output
9
正解:$dp$。
首先註意到一個性質:$m\leq 2$。
那麽我們可以考慮一下,每次一個子矩陣要麽只在第一列,要麽只在第二列,要麽橫跨兩列。
那麽我們可以設$f[i][j][k]$表示第一列到$i$,第二列到$j$,取了$k$個子矩陣的最大值,轉移比較簡單,不過註意第三種情況只有$i=j$時才能轉移。
$m=1$時同理,就是把$f[i][j][k]$換成$f[i][k]$就行了。
1 #include <bits/stdc++.h> 2 #define il inline 3 #define RG register 4 #define ll long long 5 #define inf (1<<30) 67 using namespace std; 8 9 int sum[110][2],g[110][2],n,m,k; 10 11 il int gi(){ 12 RG int x=0,q=1; RG char ch=getchar(); 13 while ((ch<‘0‘ || ch>‘9‘) && ch!=‘-‘) ch=getchar(); 14 if (ch==‘-‘) q=-1,ch=getchar(); 15 while (ch>=‘0‘ && ch<=‘9‘) x=x*10+ch-48,ch=getchar();16 return q*x; 17 } 18 19 namespace dp1{ 20 21 int f[110][12]; 22 23 int main(){ 24 for (RG int i=0;i<=n;++i) 25 for (RG int j=1;j<=k;++j) f[i][j]=-inf; 26 for (RG int i=1;i<=n;++i) 27 for (RG int j=1;j<=k;++j){ 28 f[i][j]=max(f[i][j],f[i-1][j]); 29 for (RG int p=0;p<i;++p) 30 f[i][j]=max(f[i][j],f[p][j-1]+sum[i][1]-sum[p][1]); 31 } 32 cout<<f[n][k]; return 0; 33 } 34 35 } 36 37 namespace dp2{ 38 39 int f[110][110][12]; 40 41 int main(){ 42 for (RG int i=0;i<=n;++i) 43 for (RG int j=0;j<=n;++j) 44 for (RG int p=1;p<=k;++p) f[i][j][p]=-inf; 45 for (RG int i=1;i<=n;++i) 46 for (RG int j=1;j<=n;++j) 47 for (RG int p=1;p<=k;++p){ 48 f[i][j][p]=max(f[i][j][p],f[i-1][j][p]); 49 f[i][j][p]=max(f[i][j][p],f[i][j-1][p]); 50 for (RG int pre=0;pre<i;++pre) 51 f[i][j][p]=max(f[i][j][p],f[pre][j][p-1]+sum[i][1]-sum[pre][1]); 52 for (RG int pre=0;pre<j;++pre) 53 f[i][j][p]=max(f[i][j][p],f[i][pre][p-1]+sum[j][2]-sum[pre][2]); 54 if (i==j) 55 for (RG int pre=0;pre<i;++pre) 56 f[i][j][p]=max(f[i][j][p],f[pre][pre][p-1]+sum[i][1]-sum[pre][1]+sum[j][2]-sum[pre][2]); 57 } 58 cout<<f[n][n][k]; return 0; 59 } 60 61 } 62 63 int main(){ 64 #ifndef ONLINE_JUDGE 65 freopen("matrix.in","r",stdin); 66 freopen("matrix.out","w",stdout); 67 #endif 68 n=gi(),m=gi(),k=gi(); 69 for (RG int i=1;i<=n;++i) 70 for (RG int j=1;j<=m;++j) g[i][j]=gi(); 71 for (RG int i=1;i<=n;++i){ 72 sum[i][1]=sum[i-1][1]+g[i][1]; 73 sum[i][2]=sum[i-1][2]+g[i][2]; 74 } 75 if (m==1) dp1::main(); 76 if (m==2) dp2::main(); 77 return 0; 78 }
bzoj1084 [SCOI2005]最大子矩陣