【DP】[NOI2013]书法家
題目描述
小 E 同學非常喜歡書法,他聽說 NOI2013 已經(jīng)開始了,想題一幅 “NOI” 的字送給大家。
小 E 有一張非常神奇的紙,紙可以用一個 n 行 m 列的二維方格矩陣來表示,為了描述方便,我們定義矩陣左下角方格坐標為 (1,1),右上角方格坐標為 (m,n)。
矩陣的每個方格有一個整數(shù)的幸運值。在格子上面寫字可以增加大家的幸運度,幸運度的大小恰好是所有被筆寫到的方格的幸運值之和。現(xiàn)在你要在上面寫上 “N”, “O”, “I” 三個字母。
下面給出 3 個書法字的定義:
- Li≤Ri,Bi≤Ti
- 對任意 1<i≤K,有 Li=Ri?1+1
- 對任意 3≤i<K,有 Bi?1?1≤Ti≤Ti?1,Bi≤Bi?1
- B2>B1,T2=T1,BK?1=BK,TK?1<TK
- W≥3,H≥3
- u>RK+1
- Pi≤Gi,Qi≤Hi
- P1=P3>u+W,G1=G3
- Q1=H1=Q2?1,H2+1=Q3=H3
- P1<P2≤G2<G1
下圖是一個 “N”,“O”,“I” 的例子。
另外,所有畫的圖形均不允許超過紙張的邊界。現(xiàn)在小 E 想要知道,他能畫出的最大幸運度是多少。
輸入格式
第一行包含兩個正整數(shù) n 和 m,分別表示矩陣的行數(shù)和列數(shù)。
接下來 n 行,每行有 m 個整數(shù),第 i+1 行的第 j 個數(shù)表示格子 (j, n ? i + 1)(j,n?i+1) 的幸運值。
輸出格式
輸出一個整數(shù) T,表示小 E 能夠獲得的最大幸運度。
樣例一
input
3 13 1 1 -1 -1 1 -1 1 1 1 -1 1 1 1 1 -1 1 -1 1 -1 1 -1 1 -1 -1 1 -1 1 -1 -1 1 1 -1 1 1 1 -1 1 1 1output
24樣例二
input
3 13 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1output
-20樣例三
見樣例數(shù)據(jù)下載。
限制與約定
| 1 | =3 | =12 | [?50,50] |
| 2 | |||
| 3 | |||
| 4 | |||
| 5 | ≤10 | ≤20 | [?50,50] |
| 6 | |||
| 7 | |||
| 8 | |||
| 9 | ≤150 | ≤500 | =1 |
| 10 | |||
| 11 | ≤80 | ≤80 | [?200,200] |
| 12 | |||
| 13 | |||
| 14 | |||
| 15 | ≤150 | ≤500 | [?200,200] |
| 16 | |||
| 17 | |||
| 18 | |||
| 19 | |||
| 20 |
對于所有的測試數(shù)據(jù),保證 n≥3,m≥12。
時間限制:2s
空間限制:512MB
分析
很自然地分成9個部分進行動態(tài)規(guī)劃,即把NOI3個字母,每個字母分別從左到右分為3部分,然后逐列進行轉(zhuǎn)移。
除了N的第二部分其余的都很好轉(zhuǎn)移,具體怎么轉(zhuǎn)移的呢?其實也就是按照他的規(guī)則進行模擬,看代碼就能理解了。
代碼
#include<cstdio> #include<algorithm> #include<cstring> using namespace std; #define MAXN 150 #define MAXM 500 #define INF 0x3fffffff int a[MAXN+10][MAXM+10],n,m,blk[MAXM+10][2],f[2][10][MAXN+10][MAXN+10],s[MAXN+10][MAXM+10],tmp[MAXN+10][MAXN+10],ans=-INF; void Read(int &x){static char c;bool f(0);while(c=getchar(),c!=EOF){if(c=='-')f=1;else if(c>='0'&&c<='9'){x=c-'0';while(c=getchar(),c>='0'&&c<='9')x=x*10+c-'0';ungetc(c,stdin);if(f)x=-x;return;}} } void read(){Read(n),Read(m);int i,j;for(i=1;i<=n;i++)for(j=1;j<=m;j++){Read(a[i][j]);s[i][j]=s[i-1][j]+a[i][j];} } void dp(){int i,j,k;memset(f[1],0xb0,sizeof f[1]);for(i=1;i<=n;i++)for(j=i;j<=n;j++)f[1][1][i][j]=s[j][1]-s[i-1][1];blk[1][0]=blk[1][1]=-INF;for(k=2;k<=m;k++){memset(f[k&1],0xb0,sizeof f[k&1]);//N的第一部分for(i=1;i<=n;i++)for(j=i;j<=n;j++)f[k&1][1][i][j]=max(s[j][k]-s[i-1][k],f[(k&1)^1][1][i][j]+s[j][k]-s[i-1][k]);//N的第二部分for(i=1;i<=n;i++){tmp[i][n+1]=-INF;for(j=n;j>=i;j--)tmp[i][j]=max(tmp[i][j+1],f[(k&1)^1][1][i][j]);}for(i=1;i<=n;i++)for(j=i;j<=n;j++){f[k&1][2][i][j]=max(f[k&1][2][i][j],tmp[i][j+1]+s[j][k]-s[i-1][k]);tmp[i][j]=-INF;}for(i=1;i<=n;i++)for(j=i;j<=n;j++)tmp[j+1][j+1]=max(tmp[j+1][j+1],f[(k&1)^1][2][i][j]);for(i=1;i<=n;i++)for(j=i+1;j<=n;j++)tmp[i][j]=max(tmp[i][j],tmp[i][j-1]);for(i=1;i<=n;i++)for(j=i;j<=n;j++)f[k&1][2][i][j]=max(f[k&1][2][i][j],tmp[i][j]+s[j][k]-s[i-1][k]);for(i=1;i<=n;i++)for(j=i;j<=n;j++)tmp[i][j]=f[(k&1)^1][2][i][j];for(j=1;j<=n;j++)for(i=1;i<j;i++)tmp[i+1][j]=max(tmp[i+1][j],tmp[i][j]);for(i=1;i<=n;i++)for(j=i;j<n;j++)tmp[i][j+1]=max(tmp[i][j+1],tmp[i][j]);for(i=1;i<=n;i++)for(j=i;j<=n;j++)f[k&1][2][i][j]=max(f[k&1][2][i][j],tmp[i][j]+s[j][k]-s[i-1][k]);//N的第三部分for(i=1;i<=n;i++)for(j=i;j<=n;j++)tmp[i][j]=f[(k&1)^1][2][i][j];for(j=1;j<=n;j++)for(i=j;i>1;i--)tmp[i-1][j]=max(tmp[i-1][j],tmp[i][j]);for(i=1;i<=n;i++)for(j=i+1;j<=n;j++)f[k&1][3][i][j]=max(f[k&1][3][i][j],max(tmp[i+1][j],f[(k&1)^1][3][i][j])+s[j][k]-s[i-1][k]);//NO之間空白blk[k][0]=blk[k-1][0];for(i=1;i<=n;i++)for(j=i;j<=n;j++)blk[k][0]=max(blk[k][0],f[(k&1)^1][3][i][j]);//O的第一部分for(i=1;i<=n;i++)for(j=i+2;j<=n;j++)f[k&1][4][i][j]=blk[k-1][0]+s[j][k]-s[i-1][k];//O的第二部分for(i=1;i<=n;i++)for(j=i+2;j<=n;j++)f[k&1][5][i][j]=max(f[(k&1)^1][4][i][j],f[(k&1)^1][5][i][j])+a[i][k]+a[j][k];//O的第三部分for(i=1;i<=n;i++)for(j=i+2;j<=n;j++)f[k&1][6][i][j]=f[(k&1)^1][5][i][j]+s[j][k]-s[i-1][k];//OI之間空白blk[k][1]=blk[k-1][1];for(i=1;i<=n;i++)for(j=i;j<=n;j++)blk[k][1]=max(blk[k][1],f[(k&1)^1][6][i][j]);//I的第一部分for(i=1;i<=n;i++)for(j=i+2;j<=n;j++)f[k&1][7][i][j]=max(blk[k-1][1],f[(k&1)^1][7][i][j])+a[i][k]+a[j][k];//I的第二部分for(i=1;i<=n;i++)for(j=i+2;j<=n;j++)f[k&1][8][i][j]=max(f[(k&1)^1][7][i][j],f[(k&1)^1][8][i][j])+s[j][k]-s[i-1][k];//I的第三部分for(i=1;i<=n;i++)for(j=i+2;j<=n;j++){f[k&1][9][i][j]=max(f[(k&1)^1][8][i][j],f[(k&1)^1][9][i][j])+a[i][k]+a[j][k];ans=max(ans,f[k&1][9][i][j]);} } } int main() {read();dp();printf("%d\n",ans); }轉(zhuǎn)載于:https://www.cnblogs.com/outerform/p/5921818.html
總結(jié)
以上是生活随笔為你收集整理的【DP】[NOI2013]书法家的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 13,反转链表《剑指offer》
- 下一篇: OS10.11安装Cocoapods并集