厦门大学算法课调制四果汤

题目链接:

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; 
}
posted @ 2024-03-29 23:27  雪之下,树之旁  阅读(26)  评论(0编辑  收藏  举报