厦门大学算法课调制四果汤
题目链接:
https://www.luogu.com.cn/problem/U417762
预处理
题目实际上和字母没关系。直接把字母转化成01234....即可。
设置状态
设状态 \(S\) 的第 \(i\) 位表示是否获取到了第 \(i\) 种状态(\(0无1有\)),则 \(S\) 最大只需要 \(15\) 位即可,空间上允许我们将其作为数组下标。
设 \(dp[S]\) 表示在到达状态 \(S\) 所需要的最小花费。初始值设为极大,对于已有调料状态设置为对应初始值即可。
对于每个状态,遍历所有调料,有:
\(dp[S | a[i]] = min(dp[S | a[i]], dp[S] + w_i)\)
最终答案即为 \(dp[2^n - 1]\)
#include <bits/stdc++.h>
using namespace std;
#define N 15
#define ll long long
int T, n;
int dp[1 << N];
int main(){
cin >> T >> n;
for(int i = 0; i < (1 << N); i++)
dp[i] = 1e9;
vector <pair<int, int> > G;
while(T--){
int x; cin >> x;
string s;
cin >> s;
int st = 0;
for(int i = 0; i < s.length(); i++){
st |= (1 << (s[i] - 'A'));
}
dp[st] = min(dp[st], x);
G.push_back(make_pair(st, x));
}
for(int st = 0; st < (1 << n); st++){
for(int j = 0; j < G.size(); j++){
dp[st | G[j].first] = min(dp[st | G[j].first], dp[st] + G[j].second);
}
}
if(dp[(1 << n) - 1] == 1e9) cout << -1 << endl;
else cout << dp[(1 << n) - 1] << endl;
return 0;
}