【CodeForces 1042B --- Vitamins】DP+位运算

【CodeForces 1042B --- Vitamins】DP+位运算

题目来源:点击进入【CodeForces 1042B — Vitamins】

Description

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.

Sample Input

4
5 C
6 B
16 BAC
4 A

Sample Output

15

解题思路1

由于题意有三个字母ABC表示三种维生素。那么我们可以用三个二进制位表示是否含有对应的维生素。
所以我们通过arr[8]来记录000-111所有情况的最低价格。
最开始将arr数组初始化为inf。当然arr[0]=0;
每次输入一种饮料时更新所有有关arr[]的价格。
最后判断arr[7]是否等于inf。如果等于则说明无法满足题意输出-1;
反之输出arr[7]即可。

AC代码1:

#include <iostream>
#include <algorithm>
#include <cstring>
#include <string>
using namespace std;
#define SIS std::ios::sync_with_stdio(false),cin.tie(0),cout.tie(0)
#define endl '\n'
const int inf = 0x3f3f3f3f;
int arr[8];

int main()
{
    SIS;
    memset(arr,inf,sizeof(arr));
    arr[0]=0;
    int n,c;
    string s;
    cin >> n;
    while(n--)
    {
        int ss=0;
        cin >> c >> s;
        int len=s.size();
        for(int i=0;i<len;i++)
            ss|=1<<(s[i]-'A');
        for(int i=0;i<8;i++)
            arr[i|ss]=min(arr[i|ss],arr[i]+c);
    }
    if(arr[7]==inf) cout << -1 << endl;
    else cout << arr[7] << endl;
    return 0;
}

解题思路2

由于题意有三个字母ABC表示三种维生素。那么我们可以用三个二进制位表示是否含有对应的维生素。
所以我们通过arr[8]来记录000-111所有情况的最低价格。
最开始将arr数组初始化为inf。当然arr[0]=0;
每次输入一种饮料时更新当前饮料对应的维生素种类的价格。
最后暴力循环遍历所有情况使arr[7]最小化。

AC代码2:

#include <iostream>
#include <algorithm>
#include <cstring>
#include <string>
using namespace std;
#define SIS std::ios::sync_with_stdio(false),cin.tie(0),cout.tie(0)
#define endl '\n'
const int inf = 0x3f3f3f;
int arr[8];

int main()
{
    SIS;
    arr[0]=0;
    for(int i=1;i<8;i++) arr[i]=inf;
    int n,c;
    string s;
    cin >> n;
    while(n--)
    {
        int ss=0;
        cin >> c >> s;
        int len=s.size();
        for(int i=0;i<len;i++)
            ss|=1<<(s[i]-'A');
        arr[ss]=min(arr[ss],c);
    }
    int ans=inf;
    for(int i=0;i<8;i++)
        for(int j=0;j<8;j++)
            for(int k=0;k<8;k++)
                if((i|j|k) == 7) ans=min(ans,arr[i]+arr[j]+arr[k]);
    if(ans==inf) cout << -1 << endl;
    else cout << ans << endl;
    return 0;
}
发布了412 篇原创文章 · 获赞 135 · 访问量 4万+

猜你喜欢

转载自blog.csdn.net/qq_41879343/article/details/104100717