题目:

1010: 魔兽争霸之最后的反击

                                                                        Time Limit: 1000 MS Memory Limit: 65536 KB

Description

相传人族与兽族对峙了很久,双方均受到了重创,兽族趁人类没有能力发起大规模进攻之时突然袭击,想一次彻底打败人族。人类为了生存,无论老幼伤病,全部参战,兵分两路抗敌。

由于体质不同,我们以血量表示一个人的战斗力,现在给你所有人的血量,请你把人类分成战斗力最接近的两部分。注意,战斗力要最接近,不然,人族会因你而战败呦!

Input

第一行为一个整数n(1<=n<=36),表示人族的总人数。以下的n行每行一个整数,表示一个人的血量mi(即战斗力),其中1<=mi<=400.

Output

只有一行,包含两个数,即人族的每部分兵的血量总和,较小的一个值放在前面,两个数用空格分隔。

Sample Input

3

20

32

35

Sample Output

35 52

Source

SWUST



解题心得:

1、可以直接价将最大的战斗值/2,然后动态规划就行了。在规划的过程中状态有几种转移的方法。注意此题记录的都是状态(只有false和true),因为记录的是状态所以开的数组直接是bool类型就可以了,第一维是记录的物品的个数,第二维记录的是在选择第k个物品(人族的群数)的时候有多少种可能的重量(战斗力)。当可以达到这个重量的时候将这个重量记录为true。

第一种:

就是很简单的记录人群的数量和总的战斗力,直接给代码.

关于核心的动态规划解释一下:第k件物品,可以选择不装入,所以选择第k件物品的重量就是和第k-1个相同物品的状态相同。也可以选择装入,装入就必须第前一个状态【k-1】的 j-t[j] 要是true才可以转移到这个状态。

#include<bits/stdc++.h>
using namespace std;
bool dp[40][16000];//只是记录的状态bool就可以了,甚至bitset也可以;
int t[40];
int main()
{
int n;
int sum ;
while(~scanf("%d",&n))
{
memset(dp,0,sizeof(dp));
sum = 0;
for(int i=1;i<=n;i++)
{
scanf("%d",&t[i]);
sum += t[i];
}
dp[0][0] = 1;
for(int i=1;i<=n;i++)
{
for(int j=sum;j>=0;j--)
{
for(int k=1;k<=n;k++)
dp[k][j] = dp[k-1][j] | dp[k-1][j-t[k]];//这个是核心算法
}
}
for(int i=sum/2;i>=0;i--)
{
if(dp[n][i])
{
printf("%d %d\n",i,sum-i);
break;
}
}
}
}


第二种:使用滚动数组优化
因为只有前后的状态转移所以数组的第一维只需要开2就可以了,因为true都不变(可以选择不放入),所以状态的转移是将下一个的false在上一个的true之上改变为true。说不清楚了,直接贴代码。
#include<bits/stdc++.h>
using namespace std;
bool dp[2][16000];
int t[40];
int main()
{
int n;
int sum ;
while(~scanf("%d",&n))
{
memset(dp,0,sizeof(dp));
sum = 0;
for(int i=1;i<=n;i++)
{
scanf("%d",&t[i]);
sum += t[i];
}
dp[0][0] = 1;
int now;
for(int i=1;i<=n;i++)
{
for(int j=sum;j>=0;j--)
{
if(j >= t[i])
dp[i%2][j] = dp[(i+1)%2][j] | dp[(i+1)%2][j-t[i]];
else
{
if(dp[(i+1)%2][j])
dp[i%2][j] = 1;
}
}
now = i;//用来记录最后的那个数组,写的好弱智;
}
for(int i=sum/2;i>=0;i--)
{
if(dp[now%2][i])
{
printf("%d %d\n",i,sum-i);
break;
}
}
}
}

第三种:开一个一维数组直接转移就可以了

其实思想也很简单,这个状态转移不是从前面一次到后面转移,而是从后面往前面转移,所以后面的状态不会影响前面的状态,直接转移就可以了。

#include<bits/stdc++.h>
using namespace std;
bool dp[16000];
int t[40];
int main()
{
int n;
int sum ;
while(~scanf("%d",&n))
{
memset(dp,0,sizeof(dp));
sum = 0;
for(int i=1;i<=n;i++)
{
scanf("%d",&t[i]);
sum += t[i];
}
dp[0] = 1;
for(int i=1;i<=n;i++)
for(int j=sum;j>=0;j--)
{
dp[j] = dp[j] | dp[j-t[i]];
}
for(int i=sum/2;i>=0;i--)
{
if(dp[i])
{
printf("%d %d\n",i,sum-i);
break;
}
}
}
}

动态规划(入门,滚动数组,记录的都是状态):SWUSTACM-1010 魔兽争霸之最后的反击的更多相关文章

  1. 【动态规划】滚动数组的求解(C++)

    虽然接触动态规划算法已经有一段时间,给一个01背包问题,能够做到一个表格简单粗暴下去,然后求得结果,但心里总觉得对这个算法理解十分不到位,抱着对算法的热爱,网上很多大牛的算法思维实在让我佩服的五体投地 ...

  2. POJ_1159 Palindrome (线性动态规划+滚动数组)

    题意是说,给定一个字符串,问至少还需要插入多少个字符才能使得该字符串成为回文字符串. 这道题一开始做的时候用了一个简单的动态规划,开了一个5000*5000的数组,用递归形式实现,代码如下: 其中d[ ...

  3. HDU-1024 Max Sum Plus Plus 动态规划 滚动数组和转移优化

    题目链接:https://cn.vjudge.net/problem/HDU-1024 题意 给n, m和一个序列,找m个不重叠子串,使这几个子串内元素和的和最大. n<=1e6 例:1 3 1 ...

  4. POJ-1038 Bugs Integrated, Inc. (状压+滚动数组+深搜 的动态规划)

    本题的题眼很明显,N (1 <= N <= 150), M (1 <= M <= 10),摆明了是想让你用状态压缩dp. 整个思路如下:由于要填2*3或者3*2的芯片,那么就要 ...

  5. NOIP 2006 金明的预算方案(洛谷P1064,动态规划递推,01背包变形,滚动数组)

    一.题目链接:P1064 金明的预算方案 二.思路 1.一共只有五种情况 @1.不买 @2.只买主件 @3.买主件和附件1(如果不存在附件也要运算,只是这时附件的数据是0,也就是算了对标准的结果也没影 ...

  6. 2021.12.10 P2516 [HAOI2010]最长公共子序列(动态规划+滚动数组)

    2021.12.10 P2516 [HAOI2010]最长公共子序列(动态规划+滚动数组) https://www.luogu.com.cn/problem/P2516 题意: 给定字符串 \(S\) ...

  7. 动态规划+滚动数组 -- POJ 1159 Palindrome

    给一字符串,问最少加几个字符能够让它成为回文串. 比方 Ab3bd 最少须要两个字符能够成为回文串 dAb3bAd 思路: 动态规划 DP[i][j] 意味着从 i 到 j 这段字符变为回文串最少要几 ...

  8. 【动态规划】【滚动数组】【bitset】XVII Open Cup named after E.V. Pankratiev Stage 14, Grand Prix of Tatarstan, Sunday, April 2, 2017 Problem J. Terminal

    有两辆车,容量都为K,有n(10w)个人被划分成m(2k)组,依次上车,每个人上车花一秒.每一组的人都要上同一辆车,一辆车的等待时间是其停留时间*其载的人数,问最小的两辆车的总等待时间. 是f(i,j ...

  9. 【Java】【滚动数组】【动态规划】UVA - 11137 - Ingenuous Cubrency

    滚动数组优化自己画一下就明白了. http://blog.csdn.net/u014800748/article/details/45849217 解题思路:本题利用递推关系解决.建立一个多段图,定义 ...

随机推荐

  1. javascript获取滚动条位置(兼容所有浏览器)

    有两种方式来获取浏览器滚动条的位置 第一种:document.documentElement.scrollTop 第二种:$("body").scrollTop() 第一种方式能够 ...

  2. Josn转换

    也是搬的,大家勿喷,贴出来只为了自己记忆查找 需要引用 System.Web.Extensions.dll 这个类库 命名空间: System.Web.Script.Serialization 数据结 ...

  3. Teradata 认证系列 - 2. Teradata数据库总览

    Teradata (以下简称TD) 总览本课的学习目标 描述Teradata数据库产品的功能 知晓支持的操作系统 描述Teradata的并行架构 解释线性可扩展性 列出Teradata DBA永远不需 ...

  4. C#工程缺少IIS组件无法打开的解决办法

    作者:朱金灿 来源:http://blog.csdn.net/clever101 同事使用VS打开一个C#工程,出现下面的错误: 这个工程是C#的桌面工程,跟IIS无关,去安装IIS太麻烦了.我想到一 ...

  5. SpringBoot的核心功能

    1.独立运行的Spring项目 SpringBoot可以以jar包的形式独立运行,运行一个SpringBoot项目只需要通过java -jar xx.jar来启动. 2.内嵌Servlet容器 Spr ...

  6. Nodejs入门边读边想边记(-)

    Node入门>>一本全面的Node.js教程网站地址:http://www.nodebeginner.org/index-zh-cn.html 本文记录我在阅读上面这个网站的过程中得到的一 ...

  7. LeetCode Number of 1 Bits 计算1的个数

    题意: 提供一个无符号32位整型uint32_t变量n,返回其二进制形式的1的个数. 思路: 考察二进制的特性,设有k个1,则复杂度为O(k).考虑将当前的数n和n-1做按位与,就会将n的最后一个1去 ...

  8. yield 生成器的运行机制

    yield 生成器的运行机制 当你问生成器要一个数时,生成器会执行,直至出现 yield 语句,生成器把 yield 的参数给你,之后生成器就不会往下继续运行. 当你问他要下一个数时,他会从上次的状态 ...

  9. x5webview 微信H5支付

    mWebView.setWebViewClient(new WebViewClient() { // @Override // public boolean shouldOverrideUrlLoad ...

  10. Activiti学习记录(一)

    1.工作流的概念 工作流(Workflow),就是“业务过程的部分或整体在计算机应用环境下的自动化”,它主要解决的是“使在多个参与者之间按照某种预定义的规则传递文档.信息或任务的过程自动进行,从而实现 ...