見題:
很水的一題,資料範圍太小,字首和加爆搜就行.
#includeusing可是還是想寫正解,dp;namespace
std;
const
int maxn=110
;int ans=1
,m,n,sum[maxn][maxn];
inline
intread()
while
(isdigit(ch))
return x*ff;
}inline
void put(int
x)int
main()
}for(int len=2;len<=min(n,m);len++)}}
put(ans);
return0;
}
對於這類的二維dp,個人理解就是如果儲存的從起點到終點的狀態會被一些情況所中斷,就要只考慮最下角的點所儲存的點的狀態,例如此題,我們可以儲存以(i,j)為右下角的狀態,以f[i][j]儲存以(i,j)為最右下角的最大正方形邊長.狀態轉移怎麼樣呢?
這是我們我們可以輕易的想起二維的字首和:f[i][j]=f[i-1][j]+f[i][j-1]-f[i-1][j-1]+a[i][j],那這個能否用字首和處理呢,見下圖:
最右下的小矩陣代表(i,j)可以很清楚地看出由左邊的點,上邊的點,左上角的點三個點的最小矩陣構成以個完整的矩陣,即:if(a[i][j]==1) f[i][j]=min(f[i-1][j-1],min(f[i-1][j],f[i][j-1]))+1;
這也提醒我們min的意義就是幾個狀態都具備的共同元素.
這一題就不能用暴力了,(n<=2600,m<=2600)只能想正解,和上一題一樣我們可以用f[i][j]一(i,j)儲存合法的吃到的最大的魚的個數.
接下來就考慮狀態怎麼轉移,我自己也是嗑了許多時間還沒做出來,於是就看了題解...
給出**:
#includeusing啟示我們可以直接從最優解的轉移推狀態轉移方程...namespace
std;
#define _ 0
const
int maxn=2600
;int
m,n,a[maxn][maxn],f[maxn][maxn],s1[maxn][maxn],s2[maxn][maxn],ans;
inline
intread()
while
(isdigit(ch))
return x*ff;
}inline
void put(int
x)int
main()
for(int i=1;i<=n;i++)
if(a[i][j])}}
memset(f,
0,sizeof
(f));
memset(s1,
0,sizeof
(s1));
memset(s2,
0,sizeof
(s2));
for(int i=1;i<=n;i++)
if(a[i][j])}}
put(ans);
return (0^_^0
);}
最大子矩陣 DP
time limit 10000ms memory limit 165888kb 64bit io format lld llu hysbz 1084 這裡有乙個n m的矩陣,請你選出其中k個子矩陣,使得這個k個子矩陣分值之和最大。注意 選出的k個子矩陣不能相互重疊。第一行為n,m,k 1 n 10...
最大子矩陣 dp
已知矩陣的大小定義為矩陣中所有元素的和。給定乙個矩陣,你的任務是找到最大的非空 大小至少是1 1 子矩陣。比如,如下4 4的矩陣 0 2 7 0 9 2 6 2 4 1 4 1 1 8 0 2 的最大子矩陣是 9 2 4 1 1 8 這個子矩陣的大小是15。輸入是乙個n n的矩陣。輸入的第一行給出n...
最大子矩陣問題 dp
e acmer 題意 給你乙個矩陣,求它的所有元素和最大的子矩陣.分析 我們只知道一維的情況就是經典的最大子段和.然而維數達到二維就變的複雜了.我們觀察資料範圍500,易想到n3 的演算法也能過.純暴力是n4 的方法 然後可以通過列舉其中一維,dp最後一維的方法求出.處理列上的和為字首和,然後列舉列...