UVa 10817 - Headmaster's Headache (狀壓dp)
阿新 • • 發佈:2021-07-28
題目連結:https://onlinejudge.org/index.php?option=com_onlinejudge&Itemid=8&page=show_problem&problem=1758
設 \(dp[i][s1][s2]\) 表示前 \(i\) 個人,被恰好一個人教的課程集合為 \(s1\),被至少兩個人教點的課程集合為 \(s2\),因為狀態的原因,轉移只能使用刷表法
#include<bits/stdc++.h> using namespace std; typedef long long ll; const int maxn = 130; const int INF = 0x3f3f3f3f; int s, m, n; int c[maxn], sub[maxn]; int dp[maxn][1 << 9][1 << 9]; ll read(){ ll s = 0, f = 1; char ch = getchar(); while(ch < '0' || ch > '9'){ if(ch == '-') f = -1; ch = getchar(); } while(ch >= '0' && ch <= '9'){ s = s * 10 + ch - '0'; ch = getchar(); } return s * f; } int main(){ while(scanf("%d%d%d", &s, &m, &n) == 3 && s){ memset(sub, 0, sizeof(sub)); string in; for(int i = 1 ; i <= m + n ; ++i){ scanf("%d", &c[i]); getline(cin, in); int len = in.length(); for(int j = 0 ; j < len ; ++j){ if(in[j] >= '0' && in[j] <= '9'){ sub[i] |= (1 << (in[j] - '1')); } } } memset(dp, 0x3f, sizeof(dp)); dp[0][0][0] = 0; for(int i = 0 ; i < m + n ; ++i){ for(int s1 = 0 ; s1 < (1 << s) ; ++s1){ for(int s2 = 0 ; s2 < (1 << s) ; ++s2){ if(s1 & s2) continue; int s0 = ((1 << s) - 1) ^ (s1 | s2); // 不選 if(i+1 > m) dp[i+1][s1][s2] = min(dp[i+1][s1][s2], dp[i][s1][s2]); // 選 int ns2 = s2 | (s1 & sub[i+1]); int ns1 = (s1^(s1 & sub[i+1])) | (s0 & sub[i+1]); dp[i+1][ns1][ns2] = min(dp[i+1][ns1][ns2], dp[i][s1][s2] + c[i+1]); } } } printf("%d\n", dp[m+n][0][(1<<s)-1]); } return 0; }