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];
    }
};
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章