Codeforces 101206 H & HDU 6006 Engineer Assignment

来源:互联网 发布:软件版权声明格式 编辑:程序博客网 时间:2024/06/07 05:03

题意:给定N个任务和M个工程师。每个任务PiAi个部件Cij组成。每个工程师Ei能够处理Bi个部件Cij。每个工程师只能处理一个任务。一个任务可以由多个工程师处理。一个任务当且仅当所有部件被处理后才算被完全解决。问如何安排能够使得完成的任务数目最多。

数据范围:

1N,M10

1C100

1A,B3

思路:预处理每个任务Pi能由哪些工程书处理。

那么对于状态:

dp[N][1<<M]

有:

dp[i][j]=MIN(dp[i][j],dp[i1][k|up]+1)

其中dp[i][j]表示前i个任务工程师工作状态为j的最大任务完成数。

#include<iostream>#include<cstdio>#include<cmath>#include<string>#include<cstring>#include<stack>#include<queue>#include<map>#include<algorithm>#include<bitset>#include<vector>#include <functional>using namespace std;typedef long long ll;typedef pair<ll, ll>pii;typedef bitset<101> bs;#define sp system("pause")bs p[15], e[15];vector<int>pw[15];int dp[15][(1 << 13)];void init(){    memset(dp, -1, sizeof dp);    for (int i = 0; i < 15; i++)p[i].reset(), e[i].reset(),pw[i].clear();}int main(){    int T;    cin >> T;    int cas = 1;    while (T--)    {        init();        int n, m;        scanf("%d%d", &n, &m);        for (int i = 0; i < n; i++)        {            int x;            scanf("%d", &x);            for (int j = 0; j < x; j++)            {                int y;                scanf("%d", &y);                p[i][y] = 1;            }        }        for (int i = 0; i < m; i++)        {            int x;            scanf("%d", &x);            for (int j = 0; j < x; j++)            {                int y;                scanf("%d", &y);                e[i][y] = 1;            }        }        for (int i = 0; i < n; i++)        {            for (int j = 0; j < (1 << m); j++)            {                bs now;                for (int k = 0; k < m; k++)if (j&(1 << k))now |= e[k];                if ((now&p[i]) == p[i])pw[i].push_back(j);            }        }        for (int i = 0; i < pw[0].size(); i++)            dp[0][pw[0][i]] = 1;        for (int i = 0; i < (1 << m); i++)if (dp[0][i] == -1)dp[0][i] = 0;        int ans = 0;        for (int i = 1; i < n; i++)        {            for (int j = 0; j < (1 << m); j++)            {                if (dp[i - 1][j] == -1)continue;                if (dp[i][j] == -1)dp[i][j] = dp[i - 1][j];                else dp[i][j] = max(dp[i][j], dp[i - 1][j]);                for (int k = 0; k < pw[i].size(); k++)                {                    int now = pw[i][k];                    if ((now&j) == 0)                    {                        if (dp[i][now | j] == -1)dp[i][now | j] = dp[i - 1][j] + 1;                        else dp[i][now | j] = max(dp[i][now | j], dp[i - 1][j] + 1);                    }                }            }        }        for (int i = 0; i < n; i++)for (int j = 0; j < (1 << m); j++)            ans = max(ans, dp[i][j]);        printf("Case #%d: %d\n", cas++, ans);    }}
原创粉丝点击