Codeforces 417D.Cunning Gena (状压DP)

简介: Codeforces 417D.Cunning Gena (状压DP)

原题链接

小图非常想参加“俄罗斯密码杯”的决赛,或者至少能拿到一件 T-shirt 衫。但是比赛的题目太复杂了,所以他和 n 个朋友商量,帮他解决问题。比赛一共有 m 道题。小图知道每个朋友能解决的题目。但是他的朋友不会提供无偿帮助:第 i 个朋友要求小图支付 xi 元钱。另外还要求小图的电脑至少要连接 ki 个显示器,每个显示器的价格是 b 元钱。


小图对钱很谨慎,所以他想花尽可能少的钱来解决所有的问题。请你帮一帮小图,告诉他最少花多少元钱能解决所有题目。注意,一开始没有显示器连接到小图的电脑。


Input

第一行输入三个整数 n, m, b (1 ≤ n ≤ 100; 1 ≤ m ≤ 20; 1 ≤ b ≤ 109),分别表示小图的朋友数量,问题的数量和一台显示器的成本。


接下来输入的 2n 行数据描述了这些朋友各自的要求。第 2i 和 (2i + 1) 行包含关于第 i 个朋友的信息。第 2i 行包含三个整数 xi, ki 和 mi (1 ≤ xi ≤ 109; 1 ≤ ki ≤ 109; 1 ≤ mi ≤ m),分别表示该朋友想要的钱数,监视器个数和他可以解决的问题的数量。第 (2i + 1) 行包含 mi 个不同的正整数,表示第 i 个朋友可以解决的问题的编号。问题的编号从 1 到 m。


Output

输出小图解决所有题目要花费的最少的钱。


如果没有满足条件的结果,请输出 -1。


Examples

Input

2 2 1

100 1 1

2

100 2 1

1

Output

202

Input

3 2 5

100 1 1

1

100 1 1

2

200 1 2

1 2

Output

205

Input

1 2 1

1 1 1

1

Output

-1


思路:

m的范围很小,考虑用二进制来表示某个问题是否被解决.

dp[i]表示状态为i时不包括显示器费用的最小花费,这样只需要枚举每个朋友可以转移哪些状态即可。

对每个朋友所需的显示器数量进行排序,这样枚举到第i个人时,所需的显示器费用是固定的。

爆ll了,要开ull.

代码:

#pragma GCC optimize(2)
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
typedef pair<ll,ll>PLL;
typedef pair<int,int>PII;
typedef pair<double,double>PDD;
#define I_int ll
inline ll read()
{
    ll x=0,f=1;
    char ch=getchar();
    while(ch<'0'||ch>'9')
    {
        if(ch=='-')f=-1;
        ch=getchar();
    }
    while(ch>='0'&&ch<='9')
    {
        x=x*10+ch-'0';
        ch=getchar();
    }
    return x*f;
}
#define read read()
#define closeSync ios::sync_with_stdio(0);cin.tie(0);cout.tie(0)
#define multiCase int T;cin>>T;for(int t=1;t<=T;t++)
#define rep(i,a,b) for(int i=(a);i<=(b);i++)
#define repp(i,a,b) for(int i=(a);i<(b);i++)
#define per(i,a,b) for(int i=(a);i>=(b);i--)
#define perr(i,a,b) for(int i=(a);i>(b);i--)
ll ksm(ll a,ll b,ll p)
{
    ll res=1;
    while(b)
    {
        if(b&1)res=res*a%p;
        a=a*a%p;
        b>>=1;
    }
    return res;
}
#define PI acos(-1)
#define x first
#define y second
const int maxn=1e6+7,inf=0x3f3f3f3f;
struct node{
    ull x,k,m;
    ull s;
}a[110];
bool cmp(node a,node b){
    return a.k<b.k;///排序后枚举到第i个所需的显示器数量就是总的数量
}
ull dp[1<<21];///dp[i]表示当前状态是i时,所需要的最小花费(不计算显示器的花费)
int main()
{
    int n=read,m=read,b=read;
    for(int i=1;i<=n;i++){
        cin>>a[i].x>>a[i].k>>a[i].m;
        for(int j=0;j<a[i].m;j++){
            ull t;cin>>t;
            a[i].s|=1<<t-1;///记录每个人能够解决的问题数
        }
    }
    sort(a+1,a+1+n,cmp);
    dp[0]=0;
    for(int i=1;i<(1<<m);i++) dp[i]=1e19;
    ull res=1e19;
    for(int i=1;i<=n;i++){
        for(int j=0;j<(1<<m);j++)
            dp[j|a[i].s]=min(dp[j|a[i].s],dp[j]+a[i].x);
        res=min(res,dp[(1<<m)-1]+a[i].k*b);
    }
    if(res==1e19) puts("-1");
    else cout<<res<<endl;
    return 0;
}
目录
相关文章
codeforces 322 B Ciel and Flowers
有红绿蓝三种颜色的画,每种拿三朵可以组成一束花,或者各拿一朵组成花束,告诉你每种花的数目,求出可能组成最多的花束。 如果你的代码过不了,考虑一下 8 8 9这种组合。 因为数据量很大,我的思想就是局部和总体采用不同的策略。
58 0
codeforces 304A. Pythagorean Theorem II
给你一个n,计算出1 ≤ a ≤ b ≤ c ≤ n.使得由abc构成的三角形满足勾股定理,c为斜边。 没有简单的方法,直接爆力,但是要注意,有些abc满足勾股定理的表达式,但不一定是三角形,所以要判断一下,根据三角形三边的性质,两边之和大于第三边,两边之差小于第三边。
76 0
codeforces 322 A Ciel and Dancing
有n个男孩和m个女孩,他们要结对跳舞,每对要有一个女孩和一个男孩,而且其中一个要求之前没有和其他人结对,求出最大可以结多少对。
46 0
|
C++
codeforces 305 C. Ivan and Powers of Two
我的思路是这样的,由2^a+2^a = 2^(a+1)可知,如果有两个连续的数a,我们可以把他们合并为a+1放入集合中,使集合中没有重复的数,我可以用stl里的set。如果想要满足题目中的要求,集合中必须有最大那个数个元素,缺多少就可以计算出来了。
36 0
C - Rumor CodeForces - 893C
C - Rumor CodeForces - 893C
99 0
|
人工智能
Codeforces 777C Alyona and Spreadsheet
C. Alyona and Spreadsheet time limit per test:1 second memory limit per test:256 megabytes input:standard input output:standard ...
1165 0
Codeforces 591B Rebranding
B. Rebranding time limit per test:2 seconds memory limit per test:256 megabytes input:standard input output:standard output ...
863 0