[部分题解]noip2013提高组Day2

积木大赛:

  之前没有仔细地想,然后就直接暴力一点(骗点分),去扫每一高度,连到一起的个数,于是2组超时

先把暴力程序贴上来(可以当对拍机)

 1 #include<iostream>
 2 #include<cstdio>
 3 using namespace std;
 4 FILE *fin = fopen("block.in","r");
 5 FILE *fout= fopen("block.out","w");
 6 int *h;
 7 int n;
 8 int maxHeight = -1;
 9 long long times = 0;
10 int main(){
11     fscanf(fin,"%d",&n);
12     h = new int[(const int)(n + 1)];
13     for(int i = 1;i <= n;i++){
14         fscanf(fin,"%d",&h[i]);
15         if(h[i] > maxHeight) maxHeight = h[i];
16     }
17     char isNew = 0x00;
18     for(int i = 1;i <= maxHeight;i++){
19         isNew = 0x00;
20         for(int j = 1;j <= n;j++){
21             if(h[j] >= i && isNew == 0){
22                 times++;
23                 isNew = 0x01;
24             }
25             if(h[j] < i && isNew== 0x01){
26                 isNew = 0x00;
27             }
28         }
29     }
30     fprintf(fout,"%ld",times);
31 }

  然而用样例来举个例子

       *
      *    *
 *    *    *         *
 *    *    *    *    *
-----------------------------
 1    2    3    4    5

  当第i列的目标高度比第(i-1)高的时候,很容易发现,需要多耗费(h[i]-h[i - 1])次操作,因为在操作使第(i-1)列达到目标高度时,第i列和目标高度还差

(h[i]-h[i - 1]),每次只能放一层的积木,所以需要多耗费(h[i]-h[i - 1])次操作。

  例如把第一层放满,其它层还需要的高度


           *
      *    *         *
-----------------------------
 1    2    3    4    5

  这样会很奇怪,为什么第5列还需要放一次呢?那是因为第一次方的区间是[1,5],每次求差相当于把这一块连续的这一块放上积木

从图中可以看出如果h[i] <= h[i - 1]则不用处理,于是我们可以得到如下递推式

       |- f[i - 1] ( h[i] <= h[i - 1] )
 f[i]=|
       |- f[i - 1] + ( h[i]-h[i - 1] ) ( h[i] > h[i - 1] )

最后,附上代码,说明长,代码不长:

 1 #include<iostream>
 2 #include<fstream>
 3 using namespace std;
 4 ifstream fin("block.in");
 5 ofstream fout("block.out");
 6 int buffer[2];
 7 int n;
 8 long long result = 0;
 9 int main(){
10     fin>>n;
11     for(int i = 1;i <= n;i++){
12         fin>>buffer[1];
13         if( buffer[1] > buffer[0] ) result += buffer[1] - buffer[0];
14         buffer[0] = buffer[1];
15     }
16     fout<<result;
17     return 0;
18 }

积木大赛



花匠:

  这道题最开始用的是DP,虽然没有优化且明知复杂度是O(N2)但还是用它去骗骗分

 1 #include<iostream>
 2 #include<cstdio>
 3 using namespace std;
 4 FILE *fin = fopen("flower.in","r");
 5 FILE *fout= fopen("flower.out","w");
 6 int *f;
 7 int *f1;
 8 int *h;
 9 int n;
10 int main(){
11     fscanf(fin,"%d",&n);
12     f = new int[(const int)(n + 1)];
13     f1 = new int[(const int)(n + 1)];
14     h = new int[(const int)(n + 1)];
15     for(int i = 1;i <= n;i++){
16         fscanf(fin,"%d",&h[i]);
17         f[i] = 1;
18         f1[i] = 1;
19     }
20     for(int i = 2;i <= n; i++){
21         for(int j = i-1;j > 0;j--){
22             if(f[j]%2 == 1&&h[i]>h[j]){
23                 f[i] = max( f[j] + 1,f[i]);
24             }
25             if(f1[j]%2 == 1&&h[i]<h[j]){
26                 f1[i] = max(f1[j] + 1,f1[i]);
27             }
28             if(f[j]%2 == 0&&h[i]<h[j]){
29                 f[i] = max(f[j] + 1,f[i]);
30             }
31             if(f1[j]%2 == 0&&h[i]>h[j]){
32                 f1[i] = max(f1[j] + 1,f1[i]);
33             }
34         }
35     }
36     int maxv = -1;
37     for(int i = 1;i <= n;i++){
38         maxv = max(f[i],maxv);
39         maxv = max(f1[i],maxv);
40     }
41     fprintf(fout,"%ld",maxv);
42     return 0;
43 }

  至于最简单、快捷的方法就是找拐点,一个拐点就是一个答案,至于依据嘛,画画图就能理解了

 1 #include<iostream>
 2 #include<fstream>
 3 #include<cstring>
 4 using namespace std;
 5 ifstream fin("flower.in");
 6 ofstream fout("flower.out");
 7 int n;
 8 int *h;
 9 int result = 1;
10 void init(){
11     fin>>n;
12     h = new int[(const int)(n + 1)];
13     memset(h, 0,sizeof(int)*(n + 1));
14     for(int i = 1;i <= n;i++){
15         fin>>h[i];
16     }
17 }
18 char aFlag = -1;
19 int main(){
20     init();
21     for(int i = 1;i < n; i++){
22         if(h[i] > h[i + 1] && (aFlag == 0 || aFlag == -1) ){
23             result++;
24             aFlag = 1;
25         }
26         if(h[i] < h[i + 1] && (aFlag == 1 || aFlag == -1) ){
27             result++;
28             aFlag = 0;
29         }
30     }
31     fout<<result;
32     return 0;
33 }

花匠-找拐点

时间: 2024-10-10 07:07:12

[部分题解]noip2013提高组Day2的相关文章

2016.7.12 NOIP2013提高组 day2解题报告(未完成版)

考试马不停蹄地到来,昨天的程序还没改完,今天又考了day2,虽然没有昨天那么懵逼,但还是不尽如人意,现在还没讲题,我打算先自己看一次解题报告,争取加深理解,毕竟一位前辈说过,做一套题的质量取决于题本身的质量和你思考的程度. 考试总结: 1.数据分析推测可行算法很重要,要灵活掌握常用算法的时间复杂度: 2.对拍的方式要熟练,写对拍耗费的时间过多: 3.要加强代码实现的能力,比较突出的表现就是写200-300行多函数模拟或搜索的能力: 4.不要急于写过不完的程序,要多拿一点时间来分析数据,样例不够还

[部分题解]noip2012提高组day2

这道题有多种解法,我用的是扩展欧几里得算法求到的答案 1 #include<iostream> 2 #include<fstream> 3 #include<cstdio> 4 using namespace std; 5 typedef long long ll; 6 ifstream fin("mod.in"); 7 FILE *fout = fopen("mod.out","w"); 8 void gcd

NOIP2013 提高组day2 3 华容道 BFS

描述 小 B 最近迷上了华容道,可是他总是要花很长的时间才能完成一次.于是,他想到用编程来完成华容道:给定一种局面,华容道是否根本就无法完成,如果能完成,最少需要多少时间. 小 B 玩的华容道与经典的华容道游戏略有不同,游戏规则是这样的: 在一个 n*m 棋盘上有 n*m 个格子,其中有且只有一个格子是空白的,其余 n*m-1个格子上每个格子上有一个棋子,每个棋子的大小都是 1*1 的: 有些棋子是固定的,有些棋子则是可以移动的: 任何与空白的格子相邻(有公共的边)的格子上的棋子都可以移动到空白

【解题】noip2013提高组(day1+day2)

这套题,勾起了我无数美好的回忆←意思是该好好复习了... [day1] 一.转圈游戏 首先,第一题,在处理k的时候应该用快速幂算法. 大概就是下面这样,要注意的是:1.二分时要判断有无余数.2.先设数,在进行乘积运算,不然会递归两次=.= 1 int pow(int a,int pos) 2 { 3 if(pos==1) return a%t; 4 int temp=pow(a,pos/2); 5 if(pos%2==1) return (temp*temp*a)%t; 6 return (te

【基础练习】【贪心】【递推】NOIP2013提高组第五题 积木大赛题解

还是先把题目放上吧: 春春幼儿园举办了一年一度的"积木大赛".今年比赛的内容是搭建一座宽度为n的大厦,大厦可以看成由n块宽度为1的积木组成,第n块积木的最终高度需要是hi. 在搭建开始之前,没有任何积木(可以看成n块高度为 0 的积木).接下来每次操作,小朋友们可以选择一段连续区间[L,R],然后将第L块到第R块之间(含第 L 块和第 R 块)所有积木的高度分别增加1. 小M是个聪明的小朋友,她很快想出了建造大厦的最佳策略,使得建造所需的操作次数最少.但她不是一个勤于动手的孩子,所以想

noip2014提高组day2二题题解-rLq

(又是昨天的作业……本题写于昨天) (这破题都做这么久,我是不是吃枣药丸……) (好吧这是一道图论题呢) 本题地址:http://www.luogu.org/problem/show?pid=2296 题目描述 在有向图G 中,每条边的长度均为1 ,现给定起点和终点,请你在图中找一条从起点到终点的路径,该路径满足以下条件: 1 .路径上的所有点的出边所指向的点都直接或间接与终点连通. 2 .在满足条件1 的情况下使路径最短. 注意:图G 中可能存在重边和自环,题目保证终点没有出边. 请你输出符合

2015 Noip提高组 Day2

P2678 跳石头 [题目背景] 一年一度的“跳石头”比赛又要开始了! [题目描述] 这项比赛将在一条笔直的河道中进行,河道中分布着一些巨大岩石.组委会已经选择好了两块岩石作为比赛起点和终点.在起点和终点之间,有 N 块岩石(不含起点和终 点的岩石).在比赛过程中,选手们将从起点出发,每一步跳向相邻的岩石,直至到达 终点. 为了提高比赛难度,组委会计划移走一些岩石,使得选手们在比赛过程中的最短跳 跃距离尽可能长.由于预算限制,组委会至多从起点和终点之间移走 M 块岩石(不能 移走起点和终点的岩石

【未完成0.0】Noip2012提高组day2 解题报告

第一次写一套题的解题报告,感觉会比较长.(更新中Loading....):) 题目: 第一题:同余方程 描述 求关于x的同余方程ax ≡ 1 (mod b)的最小正整数解. 格式 输入格式 输入只有一行,包含两个正整数a, b,用一个空格隔开. 输出格式 输出只有一行,包含一个正整数x0,即最小正整数解.输入数据保证一定有解. 样例1 样例输入1 3 10 样例输出1 7 限制 每个测试点1s 提示 对于40%的数据,2 ≤b≤ 1,000: 对于60%的数据,2 ≤b≤ 50,000,000:

洛谷P1967 [NOIP2013提高组Day1T2]货车运输

P1967 货车运输 题目描述 A 国有 n 座城市,编号从 1 到 n,城市之间有 m 条双向道路.每一条道路对车辆都有重量限制,简称限重.现在有 q 辆货车在运输货物, 司机们想知道每辆车在不超过车辆限重的情况下,最多能运多重的货物. 输入输出格式 输入格式: 输入文件名为 truck.in. 输入文件第一行有两个用一个空格隔开的整数 n,m,表示 A 国有 n 座城市和 m 条道 路. 接下来 m 行每行 3 个整数 x. y. z,每两个整数之间用一个空格隔开,表示从 x 号城市到 y