URAL1326. Bottle Taps(状压)

1326

用队列优化的 不知道为什么一直WA  传统直白的 状压 写了超时 O((1<<n)*m*n) 之后想了可以把n省去 预处理一下方案

 1 #include <iostream>
 2 #include<cstdio>
 3 #include<cstring>
 4 #include<algorithm>
 5 #include<stdlib.h>
 6 #include<vector>
 7 #include<cmath>
 8 using namespace std;
 9 #define N 1100000
10 #define INF 0xfffffff
11 int dp[2][N];
12 int p[25],o[110],sum[110];
13 vector<int>a[110];
14 bool f[2][N],ff[25];
15 int main()
16 {
17     int i,j,n,m,v,s=0;
18     cin>>n;
19     for(i = 1; i <= n ; i++)
20     cin>>p[i];
21     cin>>m;
22     for(i = 1; i <= m ;i++)
23     {
24         int k,b;
25         cin>>o[i]>>k;
26         for(j = 1; j <= k ; j++)
27         {
28             cin>>b;
29             sum[i]+=(1<<(b-1));
30         }
31     }
32     cin>>v;
33     for(i = 1; i <= v ; i++)
34     {
35         int x;
36         cin>>x;
37         ff[x] = 1;
38         s+=(1<<(x-1));
39     }
40     int tt[2]={0};
41     tt[0]=1;
42     for(i =0  ;i < (1<<n) ; i++)
43     dp[0][i] = dp[1][i] = INF;
44     for(i = 0; i < (1<<n)  ; i++)
45     {
46         int pp=0,flag=1;
47         for(j = 0 ; j < n ; j++)
48         {
49             if(i&(1<<j))
50             {
51                 if(!ff[j+1]) flag=0;
52                 pp+=p[j+1];
53             }
54         }
55         if(!flag) continue;
56         dp[0][i] = pp;
57     }
58     for(i = 1; i <= m ;i++)
59     {
60         int t1 = i%2,t2 = (i-1)%2;
61         for(j = 0 ; j < (1<<n) ; j++)
62         {
63             dp[t1][j] = min(dp[t1][j],dp[t2][j]);
64             if(dp[t2][j]==INF) continue;
65             dp[t1][j|sum[i]] = min(dp[t1][j|sum[i]],dp[t2][j]+o[i]);
66         }
67     }
68     int minz = INF;
69     for(i = 0 ; i < (1<<n) ; i++)
70     {
71         if((s&i)==s)
72         {
73             minz = min(minz,min(dp[0][i],dp[1][i]));
74         }
75     }
76     cout<<minz<<endl;
77     return 0;
78 }
View Code

 

转载于:https://www.cnblogs.com/shangyu/p/3544784.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值