AtCoder E - Dividing Chocolate

It is only now that I have read the wrong question during the game. . . Thought that the number of 1s to be connected cannot exceed k k ?
Topic:
Give you a rectangle, then 0 black grids and 1 white grid. Now you can cut this rectangle horizontally or vertically so that the number of white blocks in each block is <= k.
Idea: I have
encountered many such problems.
Since the range of one coordinate axis is small and the other is large, it is possible to binary enumerate the coordinate axis with a small range. Then iterate through the column judgment.
Because I didn't bring my mind when writing, various bugs were adjusted for a long time.
Then, in fact, we can directly calculate the two-dimensional prefix sum of the pre-processing, so that the constant will be smaller, who made me lose my mind, so be it.
Complexity THE ( 2 n n m ) O(2^n\cdot n\cdot m)

int w[20][2000];
int x[2000][20];
bool vis[1005];
//总体思路,先把行切开,再去切列
int main(){
    int n = read(),m = read(),k = read();
    rep(i,1,n){
        rep(j,1,m){
            char c;
            cin >> c;
            w[i][j] = c -'0';
            x[j][i] = x[j][i-1] + w[i][j];//预处理每列的前缀和
        }
    }
    int S = (1 << (n));
    int ans = INF;
    for(int q = 1;q <= S-1;++ q){//二进制枚举每种切割情况,第i位为1,则从第(i+1)行下面切一刀
        int p = q;
        p |= (1<<(n-1));//我们为了处理方便,在最后一行后面留一刀,最后减掉即可
        vector<int> Q[20];
        int  tot = 0;
        int inx = 1;//控制每个连通块的行
        bool r = 1;
        for(int i = 0;i < n;++i){
            if((p>>i)&1){
                tot ++;
                rep(j,1,m){
                    int d = x[j][i+1] - x[j][inx-1];
                    if(d > k) {r = 0;break;}
                    Q[tot].push_back(d);
                }
                inx = i + 2;
            }
            if(r == 0) break;
        }
        if(r == 0) continue;
        int h = 0;
        /*
        这儿判断列需要切几刀,我一开始想着贪心去切,取切列的最大刀数,可是一直有5组Wa,
        后来相出一种情况,发现不对劲,然后只能m*n判断了,额....刚才似乎是n*m,复杂度一样嘛......
        */
        int Sum[12] = {0};
        for(int i = 0;i <= m-1;++i){
            bool op = 1;
            for(int j = 1;j <= tot;++j){    
                Sum[j] += Q[j][i];
                if(Sum[j]>k){op = 0;break;} 
            }
            if(!op){
                h ++;
                rep(j,1,tot) Sum[j] = Q[j][i];
            }
        }
        ans = min(ans,tot-1+h);
    }
    if(ans == INF) ans = 0;
    cout << ans;
}

Published 636 original articles · praised 38 · 60,000 views +

Guess you like

Origin blog.csdn.net/qq_43408238/article/details/105120264