原题链接
小图非常想参加“俄罗斯密码杯”的决赛,或者至少能拿到一件 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; }