TopCoder SRM 667 Div1 Problem 250 - OrderOfOperations (狀壓dp)

題意

給出一些01串,我們的目標是選中全部的位置。

每選擇一個串,如果那個串中的1的位置之前沒被選過,cnt++。統計完之後,ans += cnt^2。

問如何選擇串的順序,使得最後的值最小。

思路

一開始去想貪心了,亂搞了好一會兒也搞不出來。

感覺這題用循環寫dp比用記憶化要方便一點。

我們用dp[state]表示state狀態所用的最小值。

dp[cur_state | another_state] = min(self, diff(cur_state, another_state))

意思是對於當前的狀態cur_state,枚舉s中的全部狀態another_state,新的狀態通過cur_state加上它們之間的差值來轉移。

代碼

class OrderOfOperations {
public:
    int dp[1<<21], val[100];
    int minTime(vector<string> s) {
        MS(dp, INF); MS(val, 0);
        dp[0] = 0;
        int all = 0;
        for (int i = 0; i < SZ(s); i++)
        {
            for (int j = 0; j < SZ(s[i]); j++) val[i] |= ((s[i][j]-'0')<<j);
            all |= val[i];
        }
        for (int i = 0; i <= all; i++) if (dp[i] != INF)
        {
            int cur = __builtin_popcount(i);
            for (int j = 0; j < SZ(s); j++)
            {
                int tar = i | val[j];
                int cnt = __builtin_popcount(tar);
                if (tar != i) dp[tar] = min(dp[tar], dp[i]+(cur-cnt)*(cur-cnt));
            }
        }
        return dp[all];
    }
};
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章