• CF 225C Barcode(DP)


    传送门:点我

    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 nmx 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
    ",min(dp[m][0],dp[m][1]));
    }
    /*
    6 5 1 2
    ##.#.
    .###.
    ###..
    #...#
    .##.#
    ###..
    */
                              
                                    
                                              
  • 相关阅读:
    3574. 乘积数量
    1357. 优质牛肋骨
    1356. 回文质数
    3554. 二进制
    13 vue路由跳转传参
    12 el-form的inline属性
    10 js数组赋值问题
    9 彻底搞懂json字符串和json对象
    8 element自定义卡槽的好处
    7 el-table表格中使用Dropdown 下拉菜单无法显示下拉框的问题
  • 原文地址:https://www.cnblogs.com/Esquecer/p/10543223.html
Copyright © 2020-2023  润新知