中石油训练赛 - Block(二维前缀和+思维)
題目描述
Alice得到了一張由n×m個黑白像素點組成的圖片,她想要壓縮這張圖片。壓縮圖片的過程如下:
1.首先,選擇一個正整數k(k>1),將圖片劃分成若干個k×k的小塊。如果n,m不能被k整除,用白色像素點在圖片的右邊或下面補全,使補全成n,m都能被k整除。
2.由于壓縮時每個k×k的小塊必須顏色一致(即全黑或者全白),所以需要先改變某些像素點的顏色,然后再進行壓縮。
在Alice可以自由的選擇任意一個大于1的正整數k作為小塊的邊長的情況下,請你告訴Alice,她至少需要改變多少個像素點的顏色。
?
輸入
輸入的第一行包含兩個由空格隔開的正整數n,m(2≤n,m≤1000),表示圖片的尺寸。
接下來n行,每行包含一個長度為m的”01”串,表示Alice得到的那張圖片。”0”表示一個白色像素點,”1”表示一個黑色像素點。
?
輸出
輸出一個整數,表示Alice要壓縮她的圖片至少需要改變顏色的像素點的個數。
樣例輸入?
3 5 00100 10110 11001樣例輸出?
5提示
選擇k=2,圖片被補全為,如下:
001000
101100
110010
000000
為使每個2×2的小塊顏色一致,改變顏色為,如下:
001100
001100
000000
000000
可以發現這是所有情況中改變顏色的像素點數最少的,改變了5個像素點的顏色(答案為5的改色方案不止這一種)。
題目大意:給出一個n*m的01矩陣,我們可以隨意取一個k值,滿足
問在上述兩個約束條件下,我們最少需要改變多少個數字
題目分析:這個題目的題意還是比較容易理解的,現在就在于該如何實現了,因為前一天晚上在牛客做到了一個比較類似的二維前綴和的題目,所以讀完這個題之后第一反應就是觀察一下能否用二維前綴和輔助求解,答案肯定是可以的,所以我們就可以直接維護一個二維前綴和,然后從小到大枚舉k,每次更新最終答案就可以了
對了需要注意一下,因為這個題目涉及到了邊界補零的問題,所以我們的初始矩陣不能恰好開到1e3*1e3,肯定會RE的,因為我們枚舉的k最大值是min(n,m),所以按理來說矩陣開到2e3*2e3,然后每次維護2*n*2*m的大小就足夠用了
其實一開始用二維前綴和還是蠻擔心會超時的,因為加上內層枚舉的k,總的時間復雜度到了n*n*n,題目中的n是1e3,那么放到這個題目中就是1e9,肯定必超時,但有一個細節需要注意一下,因為隨著k的增大,x和y枚舉的次數就會和k成反比,也就是說當k達到一定大小的時候,x和y的枚舉次數就會遠遠小于n,雖然這種情況下時間復雜度我也不太會算,但肯定無法到達1e9的程度,起碼1e7或1e8評測機還是頂得住的
代碼:
#include<iostream> #include<cstdlib> #include<string> #include<cstring> #include<cstdio> #include<algorithm> #include<climits> #include<cmath> #include<cctype> #include<stack> #include<queue> #include<list> #include<vector> #include<set> #include<map> #include<sstream> using namespace std;typedef long long LL;const int inf=0x3f3f3f3f;const int N=2e3+100;LL maze[N][N];int main() { // freopen("input.txt","r",stdin); // ios::sync_with_stdio(false);int n,m;scanf("%d%d",&n,&m);for(int i=1;i<=n;i++)//讀數據for(int j=1;j<=m;j++)scanf("%1lld",&maze[i][j]);for(int i=1;i<=n*2;i++)//維護二維前綴和for(int j=1;j<=m*2;j++)maze[i][j]+=maze[i-1][j]+maze[i][j-1]-maze[i-1][j-1];LL ans=inf;//初始化答案為無窮大for(int k=2;k<=min(m,n);k++)//枚舉k{LL sum=0;//記錄一下當前k的情況下的答案for(int i=k;i<=2*n;i+=k)for(int j=k;j<=2*m;j+=k){LL c=maze[i][j]-maze[i-k][j]-maze[i][j-k]+maze[i-k][j-k];sum+=min(llabs(c-1LL*k*k),c);//這里我們選取全部轉換為當前1或者0中的較小值}ans=min(ans,sum);//實時更新答案}cout<<ans<<endl;return 0; }?
超強干貨來襲 云風專訪:近40年碼齡,通宵達旦的技術人生總結
以上是生活随笔為你收集整理的中石油训练赛 - Block(二维前缀和+思维)的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 蓝桥杯 - 垒骰子(动态规划+矩阵快速幂
- 下一篇: 蓝桥杯 - 生命之树(树形dp)