NOIP 2018普及组复赛C++详细题解报告(2)
第2题 龙虎斗
一、分析
(1)ci最大值是10亿,n最大值是10万,相乘明显会超过INT_MAX,所以本题要用long long才有可能得满分。若用int,最多只能得80分。 (2)若能想到c是count的缩写,p是position的缩写,s是soldier的缩写,对理解题意会有所帮助。 (3)p1和s1是个很弱的干扰项,直接加到该位置即可。
二、算法实现
求气势差的最小值,有两种方法。 第一种方法是暴力枚举,每移动一次,就判断气势差距是不是变得更小了。这种方法,最多可能要计算10万次。通常几百万内的循环不会运行超时。
方法一 完整代码
#include <iostream>
#include <cstdio>
#include <cmath>
using namespace std;
#define LL long long
int main(){
freopen("fight.in","r",stdin);
freopen("fight.out","w",stdout);
int n, i, m, p1, p2;
cin >> n;
LL c[n + 1], s1, s2;
for(i = 1; i <= n; i++)
{
cin >> c[i];
}
cin >> m >> p1 >> s1 >> s2;
c[p1] += s1;
LL lPower = 0; // 龙势力
for(i = 1; i < m; i++)
{
lPower += c[i] * (m - i);
}
LL rPower = 0;
for(i = m + 1; i <= n; i++)
{
rPower += c[i] * (i - m);
}
//cout << lPower << ' ' << rPower << endl;
LL gap = abs(lPower - rPower); // 双方的气势差
p2 = m; //默认放在m位置
for(i = 1; i <= n; i++)
{
if(i < m) // 神兵加到左侧龙势力
{
if(abs(lPower + s2 * (m - i) - rPower) < gap)
{
gap = abs(lPower + s2 * (m - i) - rPower);
p2 = i;
}
}
else if(i > m) // 神兵加到右侧虎势力
{
if(abs(rPower + (i - m) * s2 - lPower) < gap)
{
gap = abs(rPower + (i - m) * s2 - lPower);
p2 = i;
}
}
}
cout << p2 << endl;
return 0;
}
评测结果:
第二种方法,用龙势力和虎势力的气势差除去s2,会得到s2离m号兵营的距离dist。注意dist不能定义为整数,只能定义为浮点数。当龙势力小于虎势力且距离中包含0.5时,要往左多挪一个位置,这样得到的p2与m的距离最大,从而p2取得最小值 ;当龙势力大于虎势力且距离中包含0.5时,0.5直接去掉,这样就不用往右再挪一个距离了。这样得到的p2与m的距离最小,从而p2取得最小值。 举两个例子,这两个例子里不用考虑p1和s1,对理解题意影响不大。 例1 n = 3,c1 = 10, c3 = 11,c2等于随便一个数,比如1。m = 2。s2 = 2。 在s2没放进去时,势力差gap = 虎势力 - 龙势力 = 1。dist = gap / s2 = 0.5,所以p2 = m – int(dist + 0.5) = 1,即要把s2放到1号营里。 此时龙势力 = 10 + 2 = 12, 虎势力 = 11,gap仍然是1,但此时的p2最小。
例2 n = 3,c1 = 11, c3 = 10,c2等于随便一个数,比如1。m = 2。s2 = 2。 在s2没放进去时,势力差gap = 龙势力 – 虎势力 = 1。dist = gap / s2 = 0.5,所以p2 = m + ceil(dist -0.5) = m + 0 = m,即要把s2放到中立的m号营里。 此时龙势力 = 11, 虎势力 = 10,m号营势力 = 1 + 2 = 3,gap仍然是1,此时的p2最小。
方法二完整代码
#include <iostream>
#include <cmath>
#include<cstdio>
using namespace std;
#define LL long long
int main()
{
freopen("fight21.in","r",stdin);
freopen("fight.out","w",stdout);
int n, i, m, p1, p2;
LL s1, s2;
cin >> n;
LL c[n + 1];
for(i = 1; i <= n; i++)
{
cin >> c[i];
}
cin >> m >> p1 >> s1 >> s2;
c[p1] += s1;
LL lPower = 0; // 龙势力
for(i = 1; i < m; i++)
{
lPower += c[i] * (m - i);
}
LL rPower = 0;
for(i = m + 1; i <= n; i++)
{
rPower += c[i] * (i - m);
}
//cout << lPower << ' ' << rPower << endl;
LL gap = abs(lPower - rPower); // 双方的气势差
p2 = m; // 暂放在m的位置上
float dist = gap * 1.0 / s2; // s2离m兵营的距离
if(rPower > lPower) // 虎势力大,s2要放在龙方
{
//这里floor()也可以改为int()
p2 = m - floor(dist + 0.5);
if(p2 < 1)
{
p2 = 1; // 不能越界
}
}
else if(rPower < lPower)
{
// 注意,这里0.5是要舍弃掉的,大于0.5才加1
p2 = m + ceil(dist - 0.5);
if(p2 > n)
{
p2 = n; // 不能越界
}
}
cout << p2 << endl;
return 0;
}
- ASP获取微信小程序的OpenID服务器端代码
- 手把手教你用python抢票回家过年 !(附代码)
- 技术总结:自动扩张WPF树型表格列宽
- 部署Microsoft .NET Framework 3.0[翻译]
- 性能优化总结(六):预加载、聚合SQL应用实例
- 性能优化总结(五):CSLA服务端如何使用多线程的解决方案
- 编辑-发布-开发分离:git作为NoSQL数据库
- 性能优化总结(四):预加载的设计
- 在Expression Blend中使用XAML建立3D应用程序
- 使用 Asp.net Future May 2007 开发Silverlight应用
- Rafy 领域实体框架设计 - 重构 ORM 中的 Sql 生成
- RePractise前端篇: 前端演进史
- 性能优化总结(三):聚合SQL在GIX4中的应用
- ASP.NET AJAX 控件开发基础
- JavaScript 教程
- JavaScript 编辑工具
- JavaScript 与HTML
- JavaScript 与Java
- JavaScript 数据结构
- JavaScript 基本数据类型
- JavaScript 特殊数据类型
- JavaScript 运算符
- JavaScript typeof 运算符
- JavaScript 表达式
- JavaScript 类型转换
- JavaScript 基本语法
- JavaScript 注释
- Javascript 基本处理流程
- Javascript 选择结构
- Javascript if 语句
- Javascript if 语句的嵌套
- Javascript switch 语句
- Javascript 循环结构
- Javascript 循环结构实例
- Javascript 跳转语句
- Javascript 控制语句总结
- Javascript 函数介绍
- Javascript 函数的定义
- Javascript 函数调用
- Javascript 几种特殊的函数
- JavaScript 内置函数简介
- Javascript eval() 函数
- Javascript isFinite() 函数
- Javascript isNaN() 函数
- parseInt() 与 parseFloat()
- escape() 与 unescape()
- Javascript 字符串介绍
- Javascript length属性
- javascript 字符串函数
- Javascript 日期对象简介
- Javascript 日期对象用途
- Date 对象属性和方法
- Javascript 数组是什么
- Javascript 创建数组
- Javascript 数组赋值与取值
- Javascript 数组属性和方法