bzoj 1084 DP
首先對(duì)于m==1的情況非常容易處理(其實(shí)這兒因?yàn)檫吔缥义e(cuò)了好久。。。),直接DP就好了,設(shè)f[i][k]為這個(gè)矩陣前i個(gè)選k個(gè)矩陣的最大和,那么f[i][k]=max(f[j][k-1]+sum[j+1][i]),那么對(duì)于m==2的時(shí)候類似與m=1的時(shí)候,設(shè)w[i][j][k]為左面的一行前i個(gè)中,右面的一行前j個(gè)中,一共選k個(gè)矩陣能選取得最大矩陣。
那么轉(zhuǎn)移也比較明顯,有一下幾種轉(zhuǎn)移
w[i][j][k]=max(w[i-1][j][k],w[i][j-1][k])這種情況代表什么都不選。
w[i][j][k]=max(w[ii][j][k-1]+sum[ii+1][i][0])這種情況代表在左面一行重新確定i這個(gè)位置如何選取。
類似的w[i][j][k]=max(w[i][jj][k-1]+sum[jj+1][j][1])這種情況代表在右面一行重新確定i這個(gè)位置如何選取。?
當(dāng)i==j的時(shí)候w[i][j]=max(w[ii][ii]+sum[ii+1][i][2]),這樣就代表選了一個(gè)占兩行的矩形,然后注意枚舉的邊界就可以了。
反思:開始我的想法是w[i][k]代表兩行矩陣前i個(gè)選k個(gè)矩陣的最大值,我們可以知道選取矩陣的方法肯定是若干段只選取一行的組合,然后由選取兩行的隔開,那么我們可以枚舉i代表在i出選取占兩行的矩形(這個(gè)矩形的長(zhǎng)可以為0),那么w[i][k]=max(w[j][k]+f[j+1][ii]+sum[ii][i]),這個(gè)轉(zhuǎn)移就是先枚舉上一次的斷點(diǎn),然后后枚舉上一斷點(diǎn)到i的情況,就是一段只選取一行的加上一個(gè)占兩行的最大值,那么首先要處理每一行的f[i][j][k]值,代表i,j段選取k個(gè)矩陣的最大值。后來因?yàn)檗D(zhuǎn)移的時(shí)候枚舉邊界特別麻煩,沒有調(diào)出來,再仔細(xì)想想之后發(fā)現(xiàn)這種轉(zhuǎn)移由于狀態(tài)數(shù)太少,沒辦法準(zhǔn)確的表達(dá)每一個(gè)狀態(tài),所以轉(zhuǎn)移起來非常麻煩,所以就加了一維,可以準(zhǔn)確的表達(dá)所有狀態(tài),而且轉(zhuǎn)移十分方便,復(fù)雜度也降低了一個(gè)k(因?yàn)樯弦环N方法需要枚舉左右兩行各選多少矩形),總之,還是自己太弱了。。。
/**************************************************************Problem: 1084User: BLADEVILLanguage: C++Result: AcceptedTime:88 msMemory:1672 kb ****************************************************************///By BLADEVIL #include <cstdio> #include <cstring> #include <algorithm> #define maxn 100 #define maxm 20using namespace std;int n,m,k; int a[maxn][maxn],sum[maxn][maxn],f[maxn][maxm],w[maxn][maxn][maxm];int main(){scanf("%d%d%d",&n,&m,&k);sum[0][1]=sum[0][2]=0;for (int i=1;i<=n;i++) for (int j=1;j<=m;j++) scanf("%d",&a[i][j]),sum[i][j]=sum[i-1][j]+a[i][j];if (m==1){memset(f,0,sizeof(f));for (int i=1;i<=n;i++) {f[i][0]=0;for (int l=1;l<=k;l++){f[i][l]=f[i-1][l];for (int j=0;j<i;j++){f[i][l]=max(f[i][l],f[j][l-1]+sum[i][1]-sum[j][1]);}}}printf("%d\n",f[n][k]);} else {memset(w,0,sizeof(w));for (int i=1;i<=n;i++) {for (int j=1;j<=n;j++){w[i][j][0]=0;for (int l=1;l<=k;l++){w[i][j][l]=max(w[i-1][j][l],w[i][j-1][l]);for (int ii=0;ii<i;ii++) w[i][j][l]=max(w[i][j][l],w[ii][j][l-1]+sum[i][1]-sum[ii][1]);for (int jj=0;jj<j;jj++) w[i][j][l]=max(w[i][j][l],w[i][jj][l-1]+sum[j][2]-sum[jj][2]);if (i==j)for (int jj=0;jj<i;jj++)w[i][i][l]=max(w[i][i][l],w[jj][jj][l-1]+sum[i][1]-sum[jj][1]+sum[j][2]-sum[jj][2]);}} }printf("%d\n",w[n][n][k]);}return 0; }
?
轉(zhuǎn)載于:https://www.cnblogs.com/BLADEVIL/p/3560067.html
總結(jié)
以上是生活随笔為你收集整理的bzoj 1084 DP的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: HAproxy + Keepalive实
- 下一篇: 每日英文2013.06.19