牛客練習賽49 B 筱瑪愛閱讀 子集DP

鏈接:https://ac.nowcoder.com/acm/contest/946/B
來源:牛客網
 

筱瑪愛閱讀

時間限制:C/C++ 1秒,其他語言2秒
空間限制:C/C++ 262875K,其他語言525750K
64bit IO Format: %lld

題目描述

筱瑪是一個熱愛閱讀的好筱瑪,他最喜歡的事情就是去書店買書啦!

一天,他來到一家有nn本書的書店,筱瑪十分快樂,決定把這家店裏所有的書全部買下來。

正巧今天店裏在搞促銷活動,包含若干個促銷方案。每個促銷方案是由指定的若干本書構成的集合,如果購買了該方案中所有的書,那麼其中最便宜的一本書將免費。但是,每本書只能用於一個促銷方案。

作爲店裏的VIP,筱瑪會得到nn個價格標籤。筱瑪可以給每本書挑選一個價格標籤,使得每個價格標籤和每本書一一對應。

筱瑪想要知道,在合理利用所有促銷方案的情況下,買下所有書最小要多少錢。

 

輸入描述:


 

第一行兩個數n,mn,m,分別表示書的本數和促銷方案的種數。

第二行nn個整數,表示每個價格標籤上的標註的價格。

接下來mm行,每行第一個數kk表示該促銷方案包含書的數量。接下來kk個數,表示書的編號。

輸出描述:

輸出一行一個數,表示答案。

示例1

輸入

複製

4 2
2 3 2 4
2 2 3
2 2 4

輸出

複製

8

備註:


 

對於100%的數據,1≤n≤15,1≤m≤2n−11≤n≤15,1≤m≤2n−1,所有標籤價值之和在intint範圍內。

子集DP

預處理cnt[i]  爲 i  的二進制中1的數目

dp[i]爲購買狀態爲i的書的最大優惠  

cost  先排序

每個方案貪心取最大

添加j方案   i^j是原來的方案  加上可選的最大的  cost  更新

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int maxn=(1<<15)+12;
int cost[20];
int num[maxn];
vector<int>v[maxn];
int flag[maxn];
int dp[maxn];
int cnt[maxn];
int main()
{
    int n,m,x;
    cin>>n>>m;
    ll sum=0;
    for(int i=1; i<=n; i++)
    {
        scanf("%d",&cost[i]);
        sum+=cost[i];
    }
    sort(cost+1,cost+n+1,greater<int>());
    for(int i=1; i<=m; i++)
    {
        scanf("%d",&num[i]);
        for(int j=1; j<=num[i]; j++)
        {
            scanf("%d",&x);
            v[i].push_back(x);
        }
        int mi=cost[v[i][0]];
        int tp=0;
        for(int j=0; j<v[i].size(); j++)
        {
            mi=min(cost[v[i][j]],mi);
            tp|=(1<<(v[i][j]-1));
        }
       flag[tp]=1;//標記可更新套餐
    }
    int ma=1<<n;
    for(int i=1;i<ma;i++)
        cnt[i]=cnt[(i&(i-1))]+1;//求二進制中i中1的位數
    ll ans=sum;
    for(int i=0; i<ma; i++)
    {
        int s=i;
        for(int j=s;j;j=(j-1)&s)
        {
            if(flag[j])
            {
                dp[i]=max(dp[i],dp[i^j]+cost[cnt[i]]);//更新
            }
        }
        ans=min(ans,sum-dp[i]);
    }
    cout<<ans;
    return 0;
}

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章