题目涉及算法:

  • 奖学金:结构体排序;
  • 纪念品分组:贪心;
  • 守望者的逃离:动态规划;
  • Hanoi 双塔问题:递推。

奖学金

题目链接:https://www.luogu.org/problem/P1093

这道题目就是一道简单的结构体排序。

实现代码如下:

#include <bits/stdc++.h>
using namespace std;
const int maxn = 330;
struct Student {
int id, x, y, z;
} a[maxn];
int n;
bool cmp(Student a, Student b) {
if (a.x+a.y+a.z != b.x+b.y+b.z) return a.x+a.y+a.z > b.x+b.y+b.z;
if (a.x != b.x) return a.x > b.x;
return a.id < b.id;
}
int main() {
cin >> n;
for (int i = 0; i < n; i ++) {
cin >> a[i].x >> a[i].y >> a[i].z;
a[i].id = i + 1;
}
sort(a, a+n, cmp);
for (int i = 0; i < 5; i ++)
cout << a[i].id << " " << a[i].x+a[i].y+a[i].z << endl;
return 0;
}

纪念品分组

题目链接:https://www.luogu.org/problem/P1094

本体涉及算法:贪心。

我们从小到大遍历每个元素(将这个元素作为较小的元素),找到最大的那个与其相加的不超过w的那件物品凑成一对;剩下的就单独作为一件。使用双指针法实现。

实现代码如下:

#include <bits/stdc++.h>
using namespace std;
const int maxn = 30030;
int w, n, a[maxn], cnt;
int main() {
cin >> w >> n;
for (int i = 0; i < n; i ++) cin >> a[i];
sort(a, a+n);
int i = 0, j = n-1;
while (i < j) {
if (a[i] + a[j] <= w) { i ++; j --; cnt ++; }
else { j --; cnt ++; }
}
if (i == j) cnt ++;
cout << cnt << endl;
return 0;
}

守望者的逃离

题目链接:https://www.luogu.org/problem/P1095

本题主要涉及算法:动态规划。

我们需要知道的是:一开始如果给我的魔法值 \(\ge 10\) ,那么无论如何我都会优先选择使用魔法。

所以一开始就是循环使用贪心直到我的剩余魔法值 \(\lt 10\) 为止。

那么在这种情况下,我只有三种策略走下一步:

  • 跑步:消耗1秒,前进17米;
  • 休息:消耗1秒,回复4点魔法值;
  • 闪烁(在魔法值 \(\ge 10\) 的前提下):消耗1秒,前进60米,消耗10点魔法值。

所以,如果我设 \(f[i][j]\) 表示当前在第i秒结束时,我剩余的魔法值有j点的情况下,我行走的最大距离。则, \(f[i][j]\) 应该是如下三者的最大值:

  • \(f[i-1][j] + 17\) :表示从前一秒跑步到这一秒;
  • \(f[i-1][j-4]\) :表示休息了一秒(需满足 \(j \ge 4\) );
  • \(f[i-1][j+10]\) :表示使用魔法到这一秒(需满足 \(j \ge 10\) )。

实现代码如下:

#include <bits/stdc++.h>
using namespace std;
const int maxn = 300030;
int M, S, T, f[maxn][14];
int main() {
cin >> M >> S >> T;
for (int i = 0; i <= T; i ++)
for (int j = 0; j <= 13; j ++)
f[i][j] = -1;
int s = 0, id = 0;
while (M >= 10 && id <= T) {
s += 60;
M -= 10;
id ++;
if (s >= S) {
puts("Yes");
cout << id << endl;
return 0;
}
}
if (id > T) {
puts("No");
cout << T*60 << endl;
return 0;
}
f[id][M] = s;
for (int i = id+1; i <= T; i ++) {
for (int j = 0; j <= 13; j ++) {
int tmp1 = 0; // running
if (f[i-1][j] != -1) tmp1 = f[i-1][j] + 17;
int tmp2 = 0; // take rest
if (j >= 4 && f[i-1][j-4] != -1) tmp2 = f[i-1][j-4];
int tmp3 = 0; // use magic
if (j+10 <= 13 && f[i-1][j+10] != -1) tmp3 = f[i-1][j+10] + 60;
int tmp = max(tmp1, max(tmp2, tmp3));
if (tmp > 0) f[i][j] = tmp;
if (f[i][j] >= S) {
puts("Yes");
cout << i << endl;
return 0;
}
}
}
puts("No");
s = 0;
for (int i = 0; i <= 13; i ++) s = max(s, f[T][i]);
cout << s << endl;
return 0;
}

Hanoi 双塔问题

题目链接:

这道题目相信做过递归经典问题——汉诺塔问题——的同学应该都能够直接推导出递推公式。

Hanoi它问题的递推公式是:\(f[i] = 2 \times f[i-1] + 1\) ;

而我们这里也能够很轻松推导出双塔问题的地推公式就是:

\(f[i] = 2 \times f[i-1] + 2\)

但是因为数据量比较大,所以需要使用高精度。

实现代码如下:

#include <bits/stdc++.h>
using namespace std;
const int maxn = 100010;
int a[maxn], b[maxn], c[maxn], n, t;
void init() {
a[0] = 2;
n = 1;
}
void solve() {
for (int i = 0; i < n; i ++) a[i] *= 2;
a[0] += 2;
for (int i = 0; i < n; i ++) {
a[i+1] += a[i] / 10;
a[i] %= 10;
}
if (a[n]) n ++;
}
int main() {
cin >> t;
init();
while (--t) solve();
for (int i = n-1; i >= 0; i --) cout << a[i];
cout << endl;
return 0;
}

作者:zifeiy

2007年NOIP普及组复赛题解的更多相关文章

  1. 2010年NOIP普及组复赛题解

    题目及涉及的算法: 数字统计:入门题: 接水问题:基础模拟题: 导弹拦截:动态规划.贪心: 三国游戏:贪心.博弈论. 数字统计 题目链接:洛谷 P1179 这道题目是一道基础题. 我们只需要开一个变量 ...

  2. 2017年NOIP普及组复赛题解

    题目涉及算法: 成绩:入门题: 图书管理员:模拟: 棋盘:最短路/广搜: 跳房子:RMQ/二分答案/DP(本人解法). 成绩 题目链接:https://www.luogu.org/problemnew ...

  3. 2016年NOIP普及组复赛题解

    题目涉及算法: 买铅笔:入门题: 回文日期:枚举: 海港:双指针: 魔法阵:数学推理. 买铅笔 题目链接:https://www.luogu.org/problem/P1909 设至少要买 \(num ...

  4. 2014年NOIP普及组复赛题解

    题目涉及算法: 珠心算测验:枚举: 比例简化:枚举: 螺旋矩阵:模拟: 子矩阵:状态压缩/枚举/动态规划 珠心算测验 题目链接:https://www.luogu.org/problem/P2141 ...

  5. 2013年NOIP普及组复赛题解

    题目涉及算法: 计数问题:枚举: 表达式求值:栈: 小朋友的数字:动态规划: 车站分级:最长路. 计数问题 题目链接:https://www.luogu.org/problem/P1980 因为数据量 ...

  6. 2011年NOIP普及组复赛题解

    题目涉及算法: 数字反转:模拟: 统计单词数:模拟: 瑞士轮:模拟/排序: 表达式的值:后缀表达式/DP. 数字反转 题目链接:https://www.luogu.org/problem/P1307 ...

  7. 2008年NOIP普及组复赛题解

    题目涉及算法: ISBN号码:简单字符串模拟: 排座椅:贪心: 传球游戏:动态规划: 立体图:模拟. ISBN号码 题目链接:https://www.luogu.org/problem/P1055 简 ...

  8. 2005年NOIP普及组复赛题解

    题目涉及算法: 陶陶摘苹果:入门题: 校门外的树:简单模拟: 采药:01背包: 循环:模拟.高精度. 陶陶摘苹果 题目链接:https://www.luogu.org/problem/P1046 循环 ...

  9. 2018年NOIP普及组复赛题解

    题目涉及算法: 标题统计:字符串入门题: 龙虎斗:数学题: 摆渡车:动态规划: 对称二叉树:搜索. 标题统计 题目链接:https://www.luogu.org/problem/P5015 这道题目 ...

随机推荐

  1. LUOGU 3089 后缀排序(模板)

    传送门 解题思路 这是一个神奇的算法,sa[i]表示排名第i为的元素是啥,rk[i]表示第i个元素排名是啥.然后使用基数排序+倍增的思想去处理.主要是参考的这位大佬的博客(https://www.cn ...

  2. Keil新建工程步骤

    第一步:创建工程文件夹 1.新建一个文件夹,例如: 2.在文件夹下创建子文件夹: 文件夹说明: App:存放硬件控制程序: Libraries:存放固件库: Obj:存放生成的文件: Public:存 ...

  3. man命令及help命令

    一.man命令 man命令常用工具命令 man命令是Linux下的帮助指令,通过man指令可以查看Linux中的指令帮助.配置文件帮助和编程帮助等信息. 语法: man(选项)(参数) 选项: -a: ...

  4. 遗传算法MATLAB实现(2):一元函数优化举例

    遗传算法提供了一种求解非线性.多模型.多目标等复杂系统优化问题的通用框架. 先从例子开始,慢慢再总结理论... [例]利用遗传算法计算函数f(x)=x*cos(5*pi*x)+3.5在区间[-1,2. ...

  5. Directx11教程(61) tessellation学习(3)

    原文:Directx11教程(61) tessellation学习(3)       现在我们看看在不同tess factor的情况下,三角形是如何细分的?(这儿三条边和内部tess factor值是 ...

  6. Directx11教程(44) alpha blend(1)

    原文:Directx11教程(44) alpha blend(1)    我们知道,D3D11中按Frame来渲染物体,每个Frame中又可能包含若干个primitive,如下面的示意图所示:     ...

  7. Directx11教程(14) D3D11管线(3)

    原文:Directx11教程(14) D3D11管线(3)       现在我们开始学习一些CP(command processor)的知识.参考资料: http://fgiesen.wordpres ...

  8. iOS 获取 APP 的 Launch Image

    http://www.cocoachina.com/ios/20151027/13780.html 作者:里脊串 授权本站转载. 启动图(LaunchImage)的管理其实在iOS开始中算比较简单的了 ...

  9. oracle-Mount

    执行nomount的所有工作,另外附加数据结构并与这些数据结构进行交互.这时,oracle从控制文件中获得信息. 可以执行的任务是: 执行数据库的完全恢复操作 重命名数据文件 改变数据库的归档状态. ...

  10. bzoj1579 道路升级

    Description 每天,农夫John需要经过一些道路去检查牛棚N里面的牛. 农场上有M(1<=M<=50,000)条双向泥土道路,编号为1..M. 道路i连接牛棚P1_i和P2_i ...