1. 程式人生 > >CF 225C Barcode(DP)

CF 225C Barcode(DP)

neighbour 改變 times oss sizeof main 數組 == blank

傳送門:點我

You‘ve got an n × m pixel picture. Each pixel can be white or black. Your task is to change the colors of as few pixels as possible to obtain a barcode picture.

A picture is a barcode if the following conditions are fulfilled:

  • All pixels in each column are of the same color.
  • The width of each monochrome vertical line is at least x and at most y pixels. In other words, if we group all neighbouring columns of the pixels with equal color, the size of each group can not be less than x or greater than y.

Input

The first line contains four space-separated integers n, m, x

and y (1 ≤ n, m, x, y ≤ 1000; x ≤ y).

Then follow n lines, describing the original image. Each of these lines contains exactly m characters. Character "." represents a white pixel and "#" represents a black pixel. The picture description doesn‘t have any other characters besides "." and "#".

Output

In the first line print the minimum number of pixels to repaint. It is guaranteed that the answer exists.

Examples

Input
6 5 1 2
##.#.
.###.
###..
#...#
.##.#
###..
Output
11
Input
2 5 1 1
#####
.....
Output
5

Note

In the first test sample the picture after changing some colors can looks as follows:


.##..
.##..
.##..
.##..
.##..
.##..

題意:

給定n,m,x,y。之後輸入n行m列的字符串數組,其中#表示黑色,. 表示白色。詢問的是要讓這個字符串數組,每[x,y]列是一個顏色,最少的更改次數。

看到題目猜一下是按列的DP,推了一下午結果鴿於發現初始狀態寫錯了。

dp[i][0]表示第i列為.時候的最小費用
dp[i][1]表示第i列為#時候的最小費用

轉移方程不難得到:

dp[i][0] = min(dp[i-j][1]+(p[i][0]-p[i-j][0]),dp[i][0]); 其中 x<= j <= y;
dp[i][1] = min(dp[i-j][0]+(p[i][1]-p[i-j][1]),dp[i][1]); 其中 x<= j <= y;

其中p為前綴和,即需要改變的次數,具體看代碼。

這個方程的意思是:加上i這行,起碼需要x行,最多y行,所以dp[i][k]是從dp[i-y][k]~dp[i-x][k]這一段更新上來,其中k=0或者1。

代碼:

#include<iostream>
#include<algorithm>
#include<cstring>
#include<cmath>
#include<cstdio>
using namespace std;
char mp[1001][1001];
int p[1001][2];
int dp[1001][2];
int main(){
    int n,m,x,y;
    memset(p,0,sizeof(p));
    memset(dp,0x3f,sizeof(dp));    
    scanf("%d %d %d %d",&n,&m,&x,&y);
    for(int i = 0 ; i < n ; i++){
        scanf("%s",mp[i]);
    }
    for(int i = 0 ; i < m ; i++){
        for(int j = 0 ; j < n ;j ++){
            if(mp[j][i] == #){
                p[i+1][0]++;
            }else if(mp[j][i] == .){
                p[i+1][1]++;
            }
        }
    }
    for(int i = 2; i <= m ; i ++){
        p[i][0]+=p[i-1][0];
        p[i][1]+=p[i-1][1];
    }
    // dp[i][0]表示第i列為.時候的最小費用
    // dp[i][1]表示第i列為#時候的最小費用
     dp[0][0] = dp[0][1] = 0;
    for(int i = 1 ; i <= m ; i++){
        for(int j = x ; j <= y && j <= i; j ++){
            //加上i這行起碼x行,最多y行,所以從dp[i-y]到dp[i-x]更新上來 
            dp[i][0] = min(dp[i-j][1]+(p[i][0]-p[i-j][0]),dp[i][0]);
            dp[i][1] = min(dp[i-j][0]+(p[i][1]-p[i-j][1]),dp[i][1]);
        }
    }
    printf("%d\n",min(dp[m][0],dp[m][1]));
}
/*
6 5 1 2
##.#.
.###.
###..
#...#
.##.#
###..
*/
                          
                                
                                          

CF 225C Barcode(DP)