http://acm.split.hdu.edu.cn/showproblem.php?pid=6006

比赛的时候写了一个暴力,存暴力,过了,还46ms

那个暴力的思路是,预处理can[i][j]表示第i个人能否胜任第j个项目,能胜任的条件就是它和这个项目有共同的需求。

然后暴力枚举每一个人去搭配哪一个项目,

#include <iostream>
#include <cstdio>
#include <cstring>
#include <cmath>
#include <algorithm>
#include <vector>
#include <queue>
#include <string>
#include <stack>
#include <map>
#include <set>
#include <bitset>
#include <cstdlib>
#include <ctime>
#define X first
#define Y second
#define clr(u,v); memset(u,v,sizeof(u));
#define inff() freopen("data","r",stdin);
#define out() freopen("ans","w",stdout);
#define Clear(Q); while (!Q.empty()) Q.pop();
#define pb push_back
using namespace std;
typedef long long ll;
typedef long long LL;
typedef pair <int, int> pii;
const LL INF = 1e17;
const int inf = 0x3f3f3f3f;
const int maxn = 1e2 + ;
vector<int> project[maxn], man[maxn];
int e[maxn][maxn], DFN;
bool can[][];
int n, m; // n_project, m_man
int has[][maxn];
bool need[][maxn];
int ans = ;
void dfs(int cur) {
if (cur == m + ) {
int t = ;
for (int i = ; i <= n; ++i) {
bool flag = true;
for (int j = ; j < project[i].size(); ++j) {
if (!has[i][project[i][j]]) {
flag = false;
break;
}
}
t += flag;
}
ans = max(ans, t);
return;
}
// bool can = false;
for (int i = ; i <= n; ++i) {
if (!can[cur][i]) continue;
bool flag = false;
for (int j = ; j < man[cur].size(); ++j) {
if (!need[i][man[cur][j]]) continue;
if (has[i][man[cur][j]]) continue;
flag = true;
break;
}
if (!flag) continue;
for (int j = ; j < man[cur].size(); ++j) {
has[i][man[cur][j]]++;
}
dfs(cur + );
for (int j = ; j < man[cur].size(); ++j) {
has[i][man[cur][j]]--;
}
}
dfs(cur + );
}
void work() {
memset(can, false, sizeof can);
memset(need, false, sizeof need);
memset(has, false, sizeof has);
scanf("%d%d", &n, &m);
++DFN;
for (int i = ; i <= n; ++i) { // project
int c;
scanf("%d", &c);
project[i].clear();
while (c--) {
int val;
scanf("%d", &val);
project[i].push_back(val);
e[i + m][val] = DFN;
need[i][val] = true;
}
}
for (int i = ; i <= m; ++i) { // man
int c;
scanf("%d", &c);
man[i].clear();
while (c--) {
int val;
scanf("%d", &val);
man[i].push_back(val);
e[i][val] = DFN;
}
}
for (int i = ; i <= m; ++i) { // man
for (int j = ; j <= n; ++j) { // project
for (int k = ; k <= ; ++k) { // major
if (e[i][k] == DFN && e[j + m][k] == DFN) {
can[i][j] = true;
break;
}
}
}
}
ans = ;
dfs();
static int f = ;
printf("Case #%d: %d\n", ++f, ans);
} int main()
{
#ifdef LOCAL
inff();
#endif
int T;scanf("%d",&T);
while(T--)
{
work();
}
return ;
}

正解是状压dp

其实是一个挺好想的dp

dp[i][1 << m]表示处理了前i个项目,状态是j的时候的最大完成数目。

首先预处理要完成第i个项目,状态k是否可行。然后类似于背包

给定状态s,去除子状态k后,就能完成第i项目了,所以dp[i][s] = max(dp[i][s], dp[i - ][s - k] + 1);

dp[i - 1][s - k] + 1表示用状态s - k去完成前i - 1个项目,能完成多少。

#include <iostream>
#include <cstdio>
#include <cstring>
#include <cmath>
#include <algorithm>
#include <vector>
#include <queue>
#include <string>
#include <stack>
#include <map>
#include <set>
#include <bitset>
#include <cstdlib>
#include <ctime>
#define X first
#define Y second
#define clr(u,v); memset(u,v,sizeof(u));
#define inff() freopen("data","r",stdin);
#define out() freopen("ans","w",stdout);
#define Clear(Q); while (!Q.empty()) Q.pop();
#define pb push_back
using namespace std;
typedef long long ll;
typedef long long LL;
typedef pair <int, int> pii;
const LL INF = 1e17;
const int inf = 0x3f3f3f3f;
const int maxn = 1e2 + ;
vector<int> project[maxn], man[maxn];
vector<int> state[maxn];
int solve[][maxn], DFN;
int dp[][ + ];
void work() {
int n, m; // n_project, m_man
scanf("%d%d", &n, &m);
for (int i = ; i <= n; ++i) { // project
int c;
scanf("%d", &c);
project[i].clear();
while (c--) {
int val;
scanf("%d", &val);
project[i].push_back(val);
}
}
for (int i = ; i <= m; ++i) { // man
int c;
scanf("%d", &c);
man[i].clear();
while (c--) {
int val;
scanf("%d", &val);
man[i].push_back(val);
}
}
int en = ( << m) - ;
for (int i = ; i <= n; ++i) {
state[i].clear();
for (int j = ; j <= en; ++j) {
++DFN;
for (int k = ; k <= m; ++k) {
if (j & ( << (k - ))) {
for (int d = ; d < man[k].size(); ++d) {
solve[i][man[k][d]] = DFN;
}
}
}
bool flag = true;
for (int d = ; d < project[i].size(); ++d) {
if (solve[i][project[i][d]] != DFN) {
flag = false;
break;
}
}
if (flag) state[i].push_back(j);
}
}
// for (int i = 1; i <= n; ++i) {
// for (int j = 0; j < state[i].size(); ++j) {
// printf("%d ", state[i][j]);
// }
// printf("\n");
// }
memset(dp, false, sizeof dp);
for (int i = ; i <= n; ++i) {
for (int d = ; d <= en; ++d) {
dp[i][d] = dp[i - ][d]; // 不做这个项目
for (int k = ; k < state[i].size(); ++k) {
if ((d | state[i][k]) > d) continue;
int res = d ^ state[i][k];
dp[i][d] = max(dp[i][d], dp[i - ][res] + );
}
}
}
int ans = ;
for (int i = ; i <= en; ++i) ans = max(ans, dp[n][i]);
static int f = ;
printf("Case #%d: %d\n", ++f, ans);
} int main() {
#ifdef local
freopen("data.txt", "r", stdin);
#endif
int T;
scanf("%d", &T);
while(T--) {
work();
}
return ;
}

Engineer Assignment HDU - 6006 状压dp的更多相关文章

  1. HDU 6006 状压dp

    Engineer Assignment Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Othe ...

  2. HDU 4778 状压DP

    一看就是状压,由于是类似博弈的游戏.游戏里的两人都是绝对聪明,那么先手的选择是能够确定最终局面的. 实际上是枚举最终局面情况,0代表是被Bob拿走的,1为Alice拿走的,当时Alice拿走且满足变换 ...

  3. HDU 3001 状压DP

    有道状压题用了搜索被队友骂还能不能好好训练了,, hdu 3001 经典的状压dp 大概题意..有n个城市 m个道路  成了一个有向图.n<=10: 然后这个人想去旅行.有个超人开始可以把他扔到 ...

  4. hdu 2809(状压dp)

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=2809 思路:简单的状压dp,看代码会更明白. #include<iostream> #in ...

  5. hdu 2167(状压dp)

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=2167 思路:经典的状压dp题,前后,上下,对角8个位置不能取,状态压缩枚举即可所有情况,递推关系是为d ...

  6. hdu 3254 (状压DP) Corn Fields

    poj 3254 n乘m的矩阵,1表示这块区域可以放牛,0,表示不能,而且不能在相邻的(包括上下相邻)两个区域放牛,问有多少种放牛的方法,全部不放也是一种方法. 对于每块可以放牛的区域,有放或者不放两 ...

  7. HDU 5823 (状压dp)

    Problem color II 题目大意 定义一个无向图的价值为给每个节点染色使得每条边连接的两个节点颜色不同的最少颜色数. 对于给定的一张由n个点组成的无向图,求该图的2^n-1张非空子图的价值. ...

  8. hdu 4739 状压DP

    这里有状态压缩DP的好博文 题目:题目比较神,自己看题目吧 分析: 大概有两种思路: 1.dfs,判断正方形的话可以通过枚举对角线,大概每次减少4个三角形,加上一些小剪枝的话可以过. 2.状压DP,先 ...

  9. Travel(HDU 4284状压dp)

    题意:给n个城市m条路的网图,pp在城市1有一定的钱,想游览这n个城市(包括1),到达一个城市要一定的花费,可以在城市工作赚钱,但前提有工作证(得到有一定的花费),没工作证不能在该城市工作,但可以走, ...

随机推荐

  1. 解决低版本Eclipse安装Findbugs插件无法显示问题

    问题描述 Eclipse安装Findbugs,显示安装成功,但是重启Eclipse在[Window]-[show view]-[other]中没有显示 原因 Eclipse版本太低,新版的Findbu ...

  2. 删除iCloud手机备份

    问题描述 系统9.3.5提示iCloud空间即将满,遂清理一下,发现空间主要被备份文件占用,于是想着删除备份文件,但是手机中的清理iCloud列表中并未找到相关备份文件.最终通过Mac电脑中的iClo ...

  3. PreparedStatement预编译对象实现

    模糊查询   插入 同时插入两行数据   执行更新语句 删除操作          

  4. 《Linux内核设计与实现》读书笔记(五)- 系统调用

    主要内容: 什么是系统调用 Linux上的系统调用实现原理 一个简单的系统调用的实现 1. 什么是系统调用 简单来说,系统调用就是用户程序和硬件设备之间的桥梁. 用户程序在需要的时候,通过系统调用来使 ...

  5. angular 分页2

    http://www.alliedjeep.com/2547.htm AngularJS Code (Users.js) var Users = angular.module('Users', []) ...

  6. JavsScript中JSON相关

    1.JSON.parse(jsonString) JSON.parse(jsonString):将一个JSON格式的字符串字面值,转换成JSON对象,它的逆运算方法是JSON.stringify(ob ...

  7. Zoey.Dapper--Dapper扩展之把SQL语句放到文件中

    介绍 不知道大家在用Dapper的时候SQL语句是写到哪的,目前看网上的例子都是写到类里面的. 此项目的目的是把SQL语句放到文件(xml)中 目前只是初步版本,只是说明了意图,后面会持续完善和优化 ...

  8. [SinGuLaRiTy] 分治题目复习

    [SInGuLaRiTy-1025] Copyrights (c) SinGuLaRiTy 2017. All Rights Reserved. [POJ 1905] 棍的膨胀 (Expanding ...

  9. 洛谷P3628 [APIO2010]特别行动队(斜率优化)

    传送门 先写出转移方程$$dp[i]=max\{dp[j]+a*(sum[i]-sum[j])^2+b*(sum[i]-sum[j])+c\}$$ 假设$j$比$k$更优,则有$$dp[j]+a*(s ...

  10. luogu2486 [SDOI2011]染色

    link 题目大意:给定一个N个点的树,每个点有一个颜色 有M次操作,每次可以修改树某条链所有点变成一个颜色,查询某条链上点的颜色段数 树剖,线段树维护区间合并 我的代码记录的是某个区间左端点颜色.右 ...