题目链接:https://atcoder.jp/contests/abc142/tasks/abc142_e
题意:有N个锁 M把钥匙 每把钥匙可以打开给定的门 同时每把钥匙有花费a[i],问怎么样购买钥匙能打开所有门的同时花费最少
思路:看到N很小 空间和时间都没什么问题 考虑状压dp 然后选和不选这把钥匙 就有点0类似于二维的01背包了 状压dp的处理过程注意巧用 | 运算符
因为取最小 所以 记得初始化dp 为 一个大值 然后处理好边界就没问题了
时间复杂度 O(m*(1<<n))
1 #include<bits/stdc++.h> 2 using namespace std; 3 #define ll long long 4 #define ull unsigned long long 5 #define pb push_back 6 const int maxn=2e5+10; 7 const int mod=1e9+7; 8 int a[maxn]; 9 int c[maxn]; 10 int dp[1005][(1<<12)+5]; 11 12 int main() 13 { 14 ios::sync_with_stdio(false); 15 cin.tie(0); 16 int n,m; 17 cin>>n>>m; 18 for(int i=1;i<=m;i++) 19 { 20 int x; 21 cin>>a[i]>>x; 22 int temp=0; 23 for(int j=1;j<=x;j++) 24 { 25 int y; 26 cin>>y; 27 y=1<<(y-1); 28 temp|=y; 29 } 30 c[i]=temp; 31 } 32 for(int i=0;i<=m;i++) 33 { 34 for(int j=0;j<(1<<n);j++) 35 { 36 dp[i][j]=1e9; 37 } 38 } 39 dp[0][0]=0; 40 for(int i=1;i<=m;i++) 41 { 42 for(int j=0;j<(1<<n);j++) 43 { 44 dp[i][j]=min(dp[i][j],dp[i-1][j]); 45 int k=j|c[i]; 46 dp[i][k]=min(dp[i][k],dp[i-1][j]+a[i]); 47 } 48 } 49 if(dp[m][(1<<n)-1]==1e9) 50 cout<<-1<<‘\n‘; 51 else 52 cout<<dp[m][(1<<n)-1]<<‘\n‘; 53 54 55 }
AtCoder Beginner Contest 142 E - Get Everything
原文:https://www.cnblogs.com/winfor/p/13272946.html