題意
給出一些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];
}
};