CodeForces 417D

D. Cunning Gena

Time Limit 1s
Memory Limit 256M
A boy named Gena really wants to get to the “Russian Code Cup” finals, or at least get a t-shirt. But the offered problems are too complex, so he made an arrangement with his n friends that they will solve the problems for him.

The participants are offered m problems on the contest. For each friend, Gena knows what problems he can solve. But Gena’s friends won’t agree to help Gena for nothing: the i-th friend asks Gena xi rubles for his help in solving all the problems he can. Also, the friend agreed to write a code for Gena only if Gena’s computer is connected to at least ki monitors, each monitor costs b rubles.

Gena is careful with money, so he wants to spend as little money as possible to solve all the problems. Help Gena, tell him how to spend the smallest possible amount of money. Initially, there’s no monitors connected to Gena’s computer.

Input
The first line contains three integers n, m and b (1 ≤ n ≤ 100; 1 ≤ m ≤ 20; 1 ≤ b ≤ 109) — the number of Gena’s friends, the number of problems and the cost of a single monitor.

The following 2n lines describe the friends. Lines number 2i and (2i + 1) contain the information about the i-th friend. The 2i-th line contains three integers xi, ki and mi (1 ≤ xi ≤ 109; 1 ≤ ki ≤ 109; 1 ≤ mi ≤ m) — the desired amount of money, monitors and the number of problems the friend can solve. The (2i + 1)-th line contains mi distinct positive integers — the numbers of problems that the i-th friend can solve. The problems are numbered from 1 to m.

Output
Print the minimum amount of money Gena needs to spend to solve all the problems. Or print -1, if this cannot be achieved.

Examples
input1

2 2 1
100 1 1
2
100 2 1
1

output1

202

input2

3 2 5
100 1 1
1
100 1 1
2
200 1 2
1 2

output2

205

input3

1 2 1
1 1 1
1

output3

-1

题意

有n个人可以帮你做题,让第i个人做题你必须要拥有k[i]个monitors,还要付x[i]的钱
问至少需要多少钱才能做出所有的题

Solution

其实一开始想到的就是O(n*2^m)的状压DP,这个大家应该都能想出来,但是注意一下数据范围,这样的没有任何优化的裸的O(10^8)的时间复杂度,时限只有1s根本没办法啊。。。
后来又dalao告诉我CF的评测机跑得可快了(绝对没有CCF的老年机这么慢的)
但是我一开始sb地写了一个类似于优化的东西,有个数据神奇地WA了,debug了一个上午都没过qnq
希望如果有大佬看到的话帮忙找下错(蟹蟹啦)
用了个两个滚动数组,f数组是用来存目前转移到的状态数的

/*  codeforces 417D
    author - Joker
    tags - bitmasks-dp-greedy-sortings
    compile time - 9:50 7/26/2018
    submit time - 10:43 7/26/2018
    status - WA on t6   
    submit time - 10:59 7/26/2018
    status - WA on t7
    submit time - 11:25 7/26/2018
    status - WA on t13  */

#include <iostream>
#include <string.h>
#include <algorithm>
#define N 105
#define M 21
#define INF 0x3f3f3f3f3f3f3f3f
#define LL long long

using namespace std;

LL  f[2][1 << M], dp[2][1 << M];

struct Data {
    LL x, k, sta;
}da[N];

bool cmp(Data x, Data y) {
    return x.k < y.k;
}

int main() {
    LL n, m, b, mi, v;
    cin >> n >> m >> b;
    for (LL i = 1; i <= n; ++i) {
        cin >> da[i].x >> da[i].k >> mi;
        for(LL j = 1; j <= mi; ++j) {
            cin >> v;
            da[i].sta |= (1 << (v - 1));
        }
    }
    sort(da + 1, da + n + 1, cmp);
    LL cnt = 0, cnt1, ans = INF;
    f[0][++cnt] = 0;
    dp[1][0] = 0;
    for (LL i = 1; i <= n; ++i) {
        LL t1 = i % 2;
        LL t = 1 - t1;
        memset(dp[t], 0x3f, sizeof(dp[t]));
        cnt1 = 0;
        dp[t][0] = 0;
        dp[t1][0] = 0;
        f[t][0] = 0;
        f[t1][0] = 0;
        for (LL j = 0; j <= cnt; ++j) {
            LL news = f[t][j] | da[i].sta;
            if (dp[t][news] == INF) f[t1][++cnt1] = news;
            dp[t][news] = min(dp[t][news], dp[t1][f[t][j]] + da[i].x);
            if (news == (1 << m) - 1) ans = min(dp[t][news] + da[i].k * b, ans);
        }
        cnt = cnt1;
    }
    if (ans == INF) cout << "-1" << endl;
    else cout << ans << endl;
    return 0;
}

这里是WA掉的数据
input

20 5 49
2861 8983 2
2 3
784 8430 3
1 4 5
1620 1069 1
2
3087 5088 2
2 4
3701 4255 3
1 4 5
8060 6398 2
2 5
8535 4264 2
1 4
9688 7243 3
3 4 5
9516 7770 2
3 4
5882 2436 2
3 4
1465 5869 3
3 4 5
3599 796 3
1 2 3
4236 3206 3
2 3 5
5856 5460 2
1 4
9014 4852 1
4
2242 6892 4
2 3 4 5
540 8012 2
1 5
4163 8444 2
1 2
3980 9132 3
1 2 3
3218 4175 3
1 3 4

output

172431

answer

170811

要看O(n*2^m)的源码请看from Alex
简单的状压DP这篇应该已经将得蛮清楚了。

猜你喜欢

转载自blog.csdn.net/jokingcoder/article/details/81218298