Stay Hungry,Stay Foolish!

E - Dividing Chocolate

E - Dividing Chocolate

https://atcoder.jp/contests/abc159/tasks/abc159_e

 

思路

https://www.cnblogs.com/ycx-akioi/p/AtCoder-abc159.html

行数少,列数多,

对行应用组合方法,列举每种组合情况,

对每种组合情况, 对列进行贪心获取最长串,使得串和不大于k


Code

https://atcoder.jp/contests/abc159/submissions/38903482

 

int h, w, k;
vector<vector<int>> s(16, vector<int>(1006, 0));
//int s[16][1006];
 
// prefix sum
vector<vector<int>> ps(16, vector<int>(1006, 0));
//int ps[16][1006];
 
vector<int> hcuts;
vector<int> hlines;
vector<int> vlines;
 
int main()
{
    cin >> h >> w >> k;
    
//    if(h>15 || w>105){
//        return 0;
//    }
    
    REP(i, h){
        int hi = i+1;
        
        REP(j, w){
            int wj = j+1;
            
            char one;
            cin >> one;
            
            s[hi][wj] = (one=='1'?1:0);
//            cout << s[hi][wj];
            
            ps[hi][wj] = s[hi][wj] + ps[hi-1][wj] + ps[hi][wj-1] - ps[hi-1][wj-1];
        }
//        cout << endl;
    }
    
    if (ps[h][w] <= k){
        cout << 0 << endl;
        return 0;
    }
    
    int mincuts = (h-1) * (w-1);
    
    // horizontally split
    int rc = pow(2, h-1)-1;
    for(int i=0; i<=rc; i++){
//        cout << "----------- combination i = " << i << " ----------" << endl;
        int num=i;
        // figure out cuts of horizons
 
        hcuts.clear();
        for(int j=1;num>0; j++){
//            cout << "j = " << j << endl;
//            cout << "i&j == j ===> " << ((i&j) == j) << endl;
            if(num%2==1){
                hcuts.push_back(j);
            }
            num/=2;
        }
 
//
//        cout << "------ hcuts: combination individual cases --------" << endl;
//        REP(j, hcuts.size()){
//            cout << hcuts[j] << " ";
//        }
//        cout << endl;
 
        /* hlines: 0 1 3
        ------ 0
        1 2 3
        ------ 1
        4 5 6
        7 8 9
        ----- 3
        */
        hlines.clear();
        hlines.push_back(0);
        REP(j, hcuts.size()){
            hlines.push_back(hcuts[j]);
        }
        hlines.push_back(h);
//        
//        cout << "--------- hlines --------" << endl;
//        REP(j, hlines.size()){
//            cout << hlines[j] << " ";
//        }
//        cout << endl;
        
        // vertically split
        /*
        vlines: 0 1 3
        |1|2 3|
        |4|5 6|
        |7|8 9|
        0 1   3
        */
 
        vlines.clear();
        vlines.push_back(0);
        bool hcuts_abort = false;
        while(true){
            int vline_prev = vlines[vlines.size()-1];
            int vline_now = vline_prev+1;
 
//            cout << "--> vline_prev=" << vline_prev << endl;
//            cout << "--> vline_now=" << vline_now << endl;
 
            while(vline_now<=w){
//                cout << "try vline_now, it value=" << vline_now << endl;
                int hlines_len = hlines.size();
                /*
                --------- 0
                |1|2 3|
                --------- 1
                |4|5 6|
                |7|8 9|
                --------- 3
                0 1   3
                */
                bool greatk = false;
                for(int i=1; i<hlines_len; i++){
                    int hline_prev = hlines[i-1];
                    int hline_now = hlines[i];
 
//                    cout << "hline_prev=" << hline_prev << endl;
//                    cout << "hline_now=" << hline_now << endl;
                    
                    int rectsum = ps[hline_now][vline_now]
                        - ps[hline_now][vline_prev]
                        - ps[hline_prev][vline_now]
                        + ps[hline_prev][vline_prev];
                        
//                    cout << "rectsum = " << rectsum << endl;
                    
                    if (rectsum>k){
                        // vertially first try is failed by move one step from vline_prev
                        // it means some vertial segment has greater white blocks than k in one first try
                        if(vline_now == vline_prev+1){
                            hcuts_abort = true;
                        } else {
                            vlines.push_back(vline_now-1);
                        }
 
                        greatk = true;
                        break;
                    }
                }
                
                if(greatk){
                    break;
                }
 
                vline_now++;
            }
            
            // for last vertical segment, no need to cut
            if(vline_now > w){
                break;
            }
            
            if(hcuts_abort){
                break;
            }
        }
        vlines.push_back(w);
        
        if(hcuts_abort){
//            cout << "----------- combination i = " << i << " aborted ----------" << endl;
            continue;
        }
//        
//        cout << "----------- combination i = " << i << " met, its solution ----------" << endl;
//
//        cout << "--------- hlines --------" << endl;
//        REP(j, hlines.size()){
//            cout << hlines[j] << " ";
//        }
//        cout << endl;
//
//        cout << "--------- vlines --------" << endl;
//        REP(j, vlines.size()){
//            cout << vlines[j] << " ";
//        }
//        cout << endl;
 
        int cuts_num = hlines.size() - 2 + vlines.size() - 2;
//        cout << "----- current combination cuts ------";
//        cout << cuts_num << endl;
 
        mincuts = min(mincuts, cuts_num);
    }
 
    cout << mincuts << endl;
 
    return 0;
}
 

 

posted @ 2023-02-15 21:48  lightsong  阅读(18)  评论(0编辑  收藏  举报
Life Is Short, We Need Ship To Travel