boolcanIWin(int n, int m){ if (m==0) returntrue; if (n*(n+1)/2<m) returnfalse; vector<int> dp((1<<(n+1))); returnf(n, (1<<(n+1))-1, m, dp); } boolf(int n, int st, int rest, vector<int> &dp) { if (rest<=0) returnfalse; if (dp[st]!=0) return dp[st]==1;
bool flag = 0; for (int i = 1; i<=n; i++) { if ((st&(1<<i))&&!f(n, (st^(1<<i)), rest-i, dp)) { flag = 1; break; } } dp[st] = flag?1:-1; return flag; }
boolmakesquare(vector<int>& matchsticks){ int sum = 0; for (auto it: matchsticks) { sum+=it; } if (sum%4) returnfalse;
int n = matchsticks.size(); vector<int> dp((1<<n)+1); returnf(matchsticks, sum/4, (1<<n)-1, 0, 4, dp);
} boolf(vector<int> nums, int len, int st, int cur, int re, vector<int> &dp) { if (st==0) { return re==0; } if (dp[st]) { return dp[st]==1; } bool flag = 0; for (int i = 0; i<nums.size(); i++) { if ((st&(1<<i))&&cur+nums[i]<=len) { if (cur+nums[i]==len) { flag = f(nums, len, st^(1<<i), 0, re-1, dp); } else { flag = f(nums, len, st^(1<<i), cur+nums[i], re, dp); } if (flag) break;
} intf(vector<int> &ph, int n, int m, int i, int st, vector<vector<int>>&dp) { if (st==(1<<n)-1) { return1; } if (i==m+1) { return0; } if(dp[i][st]!=-1) { return dp[i][st]; } int ans = f(ph,n, m, i+1, st, dp); int cur = ph[i]; for (int j = 0; j<n; j++) { if ((cur&(1<<j))&&(st&(1<<j))==0) { ans = (ans+f(ph,n, m, i+1, st|(1<<j), dp))%mod; }
} dp[i][st] = ans; return ans; }
例5-分配重复整数
用到的技巧:枚举st的所有子集状态
如:st目前的状态为1001100,它有多少子集状态
使用循环枚举:
1
for (int i = st, j>0; j = (j-1)&st) {...}
通过枚举quantity的每个子集,来记录每种情况所需要的重复数字个数
1 2 3 4 5 6 7 8 9 10 11
int m = quantity.size(); vector<int> sum((1<<m)); for (int i = 0; i<quantity.size(); i++) { int v = quantity[i]; int h = 1<<i; for (int j = 0; j<h; j++) { sum[h|j] = sum[j]+v; } }
bool flag = 0; int c = cnt[i]; for (int j = st; j>0; j = (j-1)&st) { if (sum[j]<=c&&f(cnt,sum, st^j, i+1, dp)) { flag = 1; break; } } if (!flag) flag = f(cnt, sum , st, i+1, dp);
boolcanDistribute(vector<int>& nums, vector<int>& quantity){ sort(nums.begin(), nums.end()); int n = 1; for (int i = 1; i<nums.size(); i++) { if (nums[i-1]!=nums[i]) n++; } vector<int> cnt(n,0); int c = 1; for (int i = 1, j = 0; i<nums.size(); i++) { if (nums[i-1]!=nums[i]) { cnt[j++] = c; c = 1; } else { c++; } }
cnt[n-1] = c; int m = quantity.size(); vector<int> sum((1<<m)); for (int i = 0; i<quantity.size(); i++) { int v = quantity[i]; int h = 1<<i; for (int j = 0; j<h; j++) { sum[h|j] = sum[j]+v; } } vector<vector<int>> dp(n, vector<int>((1<<m))); returnf(cnt, sum, (1<<m)-1, 0, dp); } boolf(vector<int>& cnt, vector<int>& sum, int st, int i, vector<vector<int>>& dp) { if (st==0) returntrue; if (cnt.size()==i) returnfalse; if (dp[i][st]) return dp[i][st] == 1; bool flag = 0; int c = cnt[i]; for (int j = st; j>0; j = (j-1)&st) { if (sum[j]<=c&&f(cnt,sum, st^j, i+1, dp)) { flag = 1; break; } } if (!flag) flag = f(cnt, sum , st, i+1, dp); dp[i][st] = flag?1:-1; return flag; }
voidsolve(){ int n, m; cin >> n >> m; map<char, int> mp = {{'r',0},{'e',1},{'d',2}}; vector<string> g(n); for (int i = 0; i<n; i++) { cin >> g[i]; }
ll mask = pow(3,n);
vector<ll> ok;
auto cost = [&](int fr, int to) { int c = 0; for (int i = 0; i<n; i++) { if(mp[g[i][fr]]!=to%3) c++; to/=3; } return c; }; for (int i = 0; i<mask; i++) { bool flag = true; int temp = i; int last = -1; for (int j = 0; j<n; j++) { int cur = temp%3; if (cur==last) { flag = false; break; } last = cur; temp/=3; } if (flag) ok.push_back(i); }
for (int i = 1; i<m; i++) { for (auto cur: ok) { int c = cost(i,cur); for (auto prv:ok) { bool flag = true; int tcur = cur, tprv = prv; for (int i = 0; i<n; i++) { if (tcur%3==tprv%3) { flag = false; break; } tcur/=3, tprv/=3; } if (flag) { dp[i][cur] = min(dp[i][cur], dp[i-1][prv]+c); } } } }
ll ans = 0x3f3f3f3f; for (auto it: ok) { ans = min(ans, dp[m-1][it]); }
cout << ans << endl;
}
intmain() { ios::sync_with_stdio(0); cin.tie(0); cout.tie(0); int tomorin=1; //cin >> tomorin; while (tomorin--) solve(); return0; }