hdu 4971

记忆花搜索   dp

#include <cstdio>
#include <cstdlib>
#include <cmath>
#include <set>
#include <stack>
#include <vector>
#include <sstream>
#include <cstring>
#include <string>
#include <map>
#include <queue>
#include <algorithm>
#include <iostream>
#define FFI freopen("in.txt", "r", stdin)
#define maxn 1010
#define INF 0x3f3f3f3f
#define inf 1000000000
#define mod 1000000007
#define ULL unsigned long long
#define LL long long
#define _setm(houge) memset(houge, INF, sizeof(houge))
#define _setf(houge) memset(houge, -1, sizeof(houge))
#define _clear(houge) memset(houge, 0, sizeof(houge))
using namespace std;

int t, n, m, ca;
int pro[25], _cost[55], g[55][55];
LL nee[25], pre[55];
bool vis[55];
int k[25], q[25][55];
map <LL, int> pp;

LL dfs(int u) {
    if(vis[u]) return pre[u];
    vis[u] = 1;
    pre[u] |= 1LL << u;
    for(int i = 0; i < m; ++ i) {
        if(g[u][i]) {
            pre[u] |= dfs(i);
        }
    }
    return pre[u];
}

int DP(LL cur) {
    if(pp.count(cur)) return pp[cur];
    int dd = 0, cc = 0;
    for(int i = 0; i < n; ++ i) {
        if((nee[i] & cur) == nee[i]) {
            dd += pro[i];
        }
    }
    for(int i = 0; i < m; ++ i) {
        if((cur & (1LL << i))) {
            cc += _cost[i];
        }
    }
    pp[cur] = dd-cc;
    for(int i = 0; i < n; ++ i) {
        if((nee[i] & cur) != nee[i]) {
            pp[cur] = max(pp[cur], DP(cur|nee[i]));
        }
    }
    return pp[cur];
}

int main () {
    // FFI;
    scanf("%d", &t);
    ca = 0;
    while(t --) {
        scanf("%d%d", &n, &m);
        _clear(nee);
        pp.clear();
        for(int i = 0; i < n; ++ i) {
            scanf("%d", &pro[i]);
        }
        for(int i = 0; i < m; ++ i) {
            scanf("%d", &_cost[i]);
        }
        for(int i = 0; i < n; ++ i) {
            scanf("%d", &k[i]);
            for(int j = 0; j < k[i]; ++ j) {
                scanf("%d", &q[i][j]);
            }
        }
        for(int i = 0; i < m; ++ i) {
            for(int j = 0; j < m; ++ j) {
                scanf("%d", &g[i][j]);
            }
        }
        _clear(pre);
        _clear(vis);
        for(int i = 0; i < m; ++ i) {
            if(!vis[i]) {
                dfs(i);
            }
        }
        for(int i = 0; i < n; ++ i) {
            for(int j = 0; j < k[i]; ++ j) {
                nee[i] |= pre[q[i][j]];
            }
        }
        printf("Case #%d: %d\n", ++ ca, DP(0));
    }
    return 0;
}

  

时间: 2024-12-15 08:20:24

hdu 4971的相关文章

HDU 4971 A simple brute force problem.(dp)

HDU 4971 A simple brute force problem. 题目链接 官方题解写的正解是最大闭合权,但是比赛的时候用状态压缩的dp也过掉了- -,还跑得挺快 思路:先利用dfs预处理出每个项目要完成的技术集合,那么dp[i][j]表示第i个项目,已经完成了j集合的技术,由于j这维很大,所以利用map去开数组 代码: #include <cstdio> #include <cstring> #include <algorithm> #include &l

【最小割】HDU 4971 A simple brute force problem.

说是最大权闭合图.... 比赛时没敢写.... 题意 一共有n个任务,m个技术 完成一个任务可盈利一些钱,学习一个技术要花费钱 完成某个任务前需要先学习某几个技术 但是可能在学习一个任务前需要学习另几个任务 求最多能赚多少钱咯 先将缩点将需要一起学掉的技术缩成一个点 建s--任务 权值为该任务盈利多少钱 建技术(缩点后)-t 权值为学习这技术的花费(总) 任务-技术 (完成该任务所需的每个技术都需要建边)权值为INF #include<stdio.h> #include<stdlib.h

HDU - 4971 A simple brute force problem. (DP)

Problem Description There's a company with several projects to be done. Finish a project will get you profits. However, there are some technical problems for some specific projects. To solve the problem, the manager will train his employee which may

HDU 4971 A simple brute force problem. 强连通缩点+最大权闭合图

题意: 给定n个项目,m个技术难题 下面一行n个数字表示每个项目的收益 下面一行m个数字表示攻克每个技术难题的花费 下面n行第i行表示 第一个数字u表示完成 i 项目需要解决几个技术难题,后面u个数字表示需要解决的问题标号. 下面m*m的矩阵 (i,j) = 1 表示要解决j问题必须先解决i问题. (若几个问题成环,则需要一起解决) 问:最大收益. 思路: 先给问题缩点一下,每个缩点后的点权就是这个点内所有点权和. 然后跑一个最大权闭合图. #include<stdio.h> #include

HDU 4971 A simple brute force problem.(最小割---最大权闭合)

题目地址:HDU 4971 比赛的时候还不会最大权闭合,当时还跟队友讨论了好长时间费用流和DP..现在看来就是一最大权闭合水题... 建图思路:源点连工程,权值为利润,汇点连科技项目,权值为花费,然后对有依赖性的连有向边.用正权值和减去最小割就是答案. #include <iostream> #include <cstdio> #include <string> #include <cstring> #include <stdlib.h> #in

HDU 4971 A simple brute force problem.(最小割,最大权闭合图)

http://acm.hdu.edu.cn/showproblem.php?pid=4971 A simple brute force problem. Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/65536 K (Java/Others) Total Submission(s): 182    Accepted Submission(s): 115 Problem Description There's a com

HDU 4971 A simple brute force problem.

A simple brute force problem. Time Limit: 1000ms Memory Limit: 65536KB This problem will be judged on HDU. Original ID: 497164-bit integer IO format: %I64d      Java class name: Main There's a company with several projects to be done. Finish a projec

HDU 4971 A simple brute force problem.(最大权闭合图)

题意:n个项目m个问题,完成每个项目有对应收入,解决每个问题需要对应花费, 给出每个项目需解决的问题以及各问题间的依赖关系,求最大利润(可完成部分或全部项目): 思路:网络流中的最大权闭合图的典型应用——利润问题,参考07年day2国家集训队胡伯涛的论文: 参考:http://blog.csdn.net/u012965890/article/details/38761043 闭合图指所有顶点的出边指向的所有顶点均在图中: 最大权闭合图:点权和最大的闭合图,即权值最大的子闭合图: 建图思路: 工程

hdu 4971 多校10最大权闭合图

/* 很明显的最大权闭合图题 */ #include<stdio.h> #include<string.h> #include<queue> using namespace std; #define N 2100 #define inf 0x3fffffff struct node { int u,v,w,next; }bian[N*N*20]; int head[N],yong,dis[N],work[N]; void init(){ yong=0; memset(h