查看: 1417|回復: 0
打印 上一主題 下一主題

[CF] 448C - Painting Fence

[複製鏈接]
  • TA的每日心情
    開心
    2015-4-12 10:09
  • 簽到天數: 137 天

    [LV.7]常住居民III

    142

    主題

    686

    帖子

    3559

    積分

    邁向天堂

    蘇多門

    Rank: 8Rank: 8

    積分
    3559

    新手達陣台南一中資訊社程式設計達人 - 2014

    跳轉到指定樓層
    樓主
    發表於 2014-7-18 14:24:51 | 只看該作者 回帖獎勵 |正序瀏覽 |閱讀模式

    趕快加入我們來參與討論吧!

    您需要 登錄 才可以下載或查看,沒有帳號?加入我們

    x
    本帖最後由 domen111 於 2014-7-18 14:24 編輯

    Codeforces Round #256 (Div. 2) - C . Painting Fence

    這題有點難,本來以為要寫不出來了,沒想到在比賽剩下24分鐘的時候解出來了,解出了這一題讓我的排名變成158,rating變1721(Candidate Master),也就是有資格比Div.1了 ,下次比賽準備被Div.1電了。


    這題有一點DP或divide and conquer的概念,用遞迴就可以輕鬆解出,程式碼短短38行,不過要想很久。

    下面是一筆測資的範例:

    遞迴第一次執行紅色部分,試看看橫向塗色或直向比較好。
    1. 若為橫向塗色,紅色有兩列,所以答案為 2+(塗上面部分的答案) ,所以就呼叫遞迴,執行黃色和綠色的部分就可以了。
    2. 若為直向塗色,總共有10個直行,所以答案就是10。
    return 1或2答案較小的那一筆

    不過如果認真想會遇到一個問題: 會不會遞迴下去的部分會影響到上一層的結果呢? 這個概念和DP很像,如果會影響到的話,這個演算法就是錯的。
    如果上層迴圈呼叫到目前迴圈,上層迴圈必定是橫向塗色,如果目前迴圈為直向塗色,將會塗到下層迴圈塗過的區域,那這樣會不會讓下層迴圈的答案變小呢? 答案是不會的,因為目前迴圈的塗色範圍不可能包含上層迴圈塗色範圍的整個橫列(否則就不會被分成兩次迴圈了)。

    My AC code:
    [C++] 純文本查看 復制代碼
    #include<iostream>
    #include<algorithm>
    using namespace std;
    int n;
    int a[6000];
    int sol(int l,int r)
    {
        //horizontal strokes
        int ans=INT_MAX;
        for(int i=l;i<=r;i++)
            ans=min(ans,a[i]);
        for(int i=l;i<=r;i++)
            if(a[i]!=0)
                a[i]-=ans;
        int tl=-1,tr=0;
        for(int i=l;i<=r+1;i++)
        {
            if(i!=r+1 && a[i]!=0)
            {
                if(tl==-1) tl=i;
                tr=i;
            }
            else if(tl!=-1)
            {
                ans+=sol(tl,tr);
                tl=-1;
            }
        }
        
        return min(ans,r-l+1);
    }
    int main()
    {
        cin>>n;
        for(int i=0;i<n;i++)
            cin>>a[i];
        cout<<sol(0,n-1);
    }
    
    蘇多門 domen111
    My Web: https://sites.google.com/site/domenprg/
    回復

    使用道具 檢舉

    您需要登錄後才可以回帖 登入 | 加入我們

    本版積分規則

    快速回覆 返回頂部 返回列表