• CodeForces 1316E. Team Building 【贪心、状压Dp】


    传送门

    题意

    (n) 个人中选 (k) 个观众,(p) 个不同位置的比赛选手,每个人做观众或比赛选手都能为队伍提升不同的强度,
    问队伍的最大强度是多少。

    题解

    因为 (p) 很小,所以 (p) 个位置的比赛选手可以状态压缩DP来选择。
    而如果把所有人以做观众能提供的强度从大到小排序之后,(k) 个观众一定是从前 (k+p) 个人中选择,
    因为如果前 (k+p) 之外有人做了观众,那么前 (k+p) 个人中肯定有人空闲并且做观众提供的强度比他更高。
    那么只有当前 (i-1) 个人中观众数量小于 (k) 并且 (ile k+p) 的时候第 (i) 个人才可以做观众。

    这道题还可以用费用流过,在官方题解的第一个讨论里面的大神有代码,
    我按最简单的方式建图跑费用流超时超的飞起,大神的思路我又没看懂,嘤语太渣
    希望用费用流做出来的大神可以留言一下为蒟蒻解答疑惑

    代码

    #include <iostream>
    #include <stdio.h>
    #include <string.h>
    #include <stdlib.h>
    #include <algorithm>
    using namespace std;
    typedef long long LL;
    const int N=1e5+10;
    const int M=1e6+10;
    int n,p,k;
    struct Node{
    	int a,p[7];
    }s[N];
    bool cmp(Node x,Node y){return x.a>y.a;}
    LL f[N][1<<7];
    
    int main(){
    	scanf("%d%d%d",&n,&p,&k);
    	for(int i=1;i<=n;i++) scanf("%d",&s[i].a);
    	for(int i=1;i<=n;i++) for(int j=0;j<p;j++) scanf("%d",&s[i].p[j]);
    	sort(s+1,s+n+1,cmp);
    	memset(f,0xc0,sizeof(f));
    	f[0][0]=0;
    	for(int i=1;i<=n;i++)
    		for(int sta=0;sta<(1<<p);sta++){
    			int cnt=0;for(int k=0;k<p;k++) cnt+=(bool)(sta&(1<<k));
    			if(i-cnt<=k&&i<=k+p) f[i][sta]=max(f[i][sta],f[i-1][sta]+s[i].a);
    			else f[i][sta]=f[i-1][sta];
    			for(int k=0;k<p;k++)
    				if(sta&(1<<k)) f[i][sta]=max(f[i][sta],f[i-1][sta-(1<<k)]+s[i].p[k]);
    		}
    	cout<<f[n][(1<<p)-1]<<endl;
    	return 0;
    }
    
  • 相关阅读:
    mvn tomcat7:help的14个命令
    leetcode Next Permutation
    leetcode Permutation
    java HashMap
    单链表反转(递归和非递归) (Java)
    java数据类型
    Multiply Strings 大数相乘 java
    SQL中如何使用UPDATE语句进行联表更新(转)
    循环建立索引
    js 跨域访问
  • 原文地址:https://www.cnblogs.com/BakaCirno/p/12420098.html
Copyright © 2020-2023  润新知