zoukankan      html  css  js  c++  java
  • [BJOI2019]排兵布阵

    题目

    原题地址

    解说

    蒟蒻刷(DP)题的时候刷到的好题。

    首先这道题很显然是一个背包,每个城堡应该被看作物品,但主要问题就在于其消耗和价值分别是什么?经过一番思考我们发现每个城堡还需要考虑不同敌人的影响,而把城堡看作一个物品就没办法考虑上这一点,怎么办?换个思路,为何不把一个背包看作一组物品呢?

    由于我们每一轮攻击中投入士兵的分配都是不变的,所以在每城堡投入一定的兵力时(s)轮下来的累计收入是可以预处理的,这样的话我们不妨把投入兵力看作消耗,累计收入看作价值,并且不难发现每个城堡的各个物品间是不能同时选择的(毕竟一个城堡只能选择一个特定的兵力投入),正好形成了一个非常裸的分组背包模型!

    时间复杂度方面,预处理为(O(ns))的,跑分组背包时理论上为(O(nsm)),极限数据时似乎达到了(10^8)水平,但事实上由于常数挺小的而且循环背包容量时可以不用跑满,所以还是可以接受的。

    具体一些细节见代码

    代码

    #include<bits/stdc++.h>
    #define re register
    using namespace std;
    int s,n,m,num[100+3][100+3],f[20000+3],ans;
    vector<int> city[100+3];
    struct thing{
    	int cost,val;
    };
    vector<thing> group[100+3];
    int main(){
    	scanf("%d%d%d",&s,&n,&m);
    	for(re int i=1;i<=s;i++){
    		for(re int j=1;j<=n;j++){
    			scanf("%d",&num[i][j]);
    			num[i][j]=num[i][j]*2+1;
    		}
    	}
    	for(re int i=1;i<=n;i++){
    		for(re int j=1;j<=s;j++) city[i].push_back(num[j][i]);
    		sort(city[i].begin(),city[i].end());
    	}
    	for(re int i=1;i<=n;i++)
    		for(re int j=0;j<city[i].size();j++)
    			group[i].push_back((thing){city[i][j],i*(j+1)});
    	for(re int g=1;g<=n;g++){
    		for(re int j=m;j>=0;j--){
    			for(re int i=0;i<group[g].size();i++){
    				if(j>=group[g][i].cost) f[j]=max(f[j],f[j-group[g][i].cost]+group[g][i].val);
    				else break;
    			}
    		}
    	}
    	printf("%d
    ",f[m]);
    	return 0;
    }
    

    幸甚至哉,歌以咏志。

  • 相关阅读:
    mkdirp——递归创建目录及其子目录
    rimraf命令 递归删除目录所有文件
    前端面试总结——http、html和浏览器篇
    meta标签
    多行文本溢出显示省略号
    ui-sref
    Angular组件之间通讯
    定义路由的state参数
    angularjs中factory, service和provider
    Oracle Spatial分区应用研究之五:不同分区粒度+本地空间索引效率对比
  • 原文地址:https://www.cnblogs.com/DarthVictor/p/13776875.html
Copyright © 2011-2022 走看看