cf 1042B(狀壓dp)

Berland shop sells n kinds of juices. Each juice has its price ci. Each juice includes some set of vitamins in it. There are three types of vitamins: vitamin “A”, vitamin “B” and vitamin “C”. Each juice can contain one, two or all three types of vitamins in it.

Petya knows that he needs all three types of vitamins to stay healthy. What is the minimum total price of juices that Petya has to buy to obtain all three vitamins? Petya obtains some vitamin if he buys at least one juice containing it and drinks it.

Input
The first line contains a single integer n (1≤n≤1000) — the number of juices.

Each of the next n lines contains an integer ci (1≤ci≤100000) and a string si — the price of the i-th juice and the vitamins it contains. String si contains from 1 to 3 characters, and the only possible characters are “A”, “B” and “C”. It is guaranteed that each letter appears no more than once in each string si. The order of letters in strings si is arbitrary.

Output
Print -1 if there is no way to obtain all three vitamins. Otherwise print the minimum total price of juices that Petya has to buy to obtain all three vitamins.

題意:數據有n組數,每組數有一個價值ci和一個字符串S,字符串S中包含3個字母A,B,C,問集齊ABC三個字母的最小价值(一個字母可以有多個)

題解:狀壓。將維生素A當做001,維生素B當做010,維生素C當做100,目標:求出狀態爲111的最小代價。
//注意這裏的|,兩個維生素同時使用,結果是它們的並集,所以是|

#include <bits/stdc++.h>
using namespace std;
const int inf = 1e9;
int dp[100];
char str[100];
int main() {
	int n, val, len, c;
	cin >> n;
	for (int i = 0; i <= 10; i++) dp[i] = inf;
	for (int i = 1; i <= n; i++) {
		cin >> c >> str;
		len = strlen(str);
		val = 0;
		for (int j = 0; j < len; j++) {
			if (str[j] == 'A') val |= 1;
			if (str[j] == 'B') val |= 2;
			if (str[j] == 'C') val |= 4;
		}
		dp[val] = min(dp[val], c);
	}
	for (int i = 0; i <= 7; i++) {
		for (int j = 0; j <= 7; j++) {
			dp[i | j] = min(dp[i | j], dp[i] + dp[j]);
		}
	}
	if (dp[7] >= inf) {
		cout << -1 << endl;
	} else {
		cout << dp[7] << endl;
	}
	return 0;
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章