写在前面:
本系列博客仅作为本人十一假期过于无聊的产物,对小学期的程序设计作业进行一个总结式的回顾,如果将来有BIT的学弟学妹们在百度搜思路时翻到了这一条博客,也希望它能对你产生一点帮助(当然,依经验来看,每年的题目也会有些许的不同,所以不能保证每一题都覆盖到,还请见谅)。
不过本人由于学艺不精,代码定有许多不足之处,欢迎各位一同来探讨。
同时请未来浏览这条博客的学弟学妹们注意,对于我给出完整代码的这些题,仅作帮助大家理解思路所用(当然,因为懒,所以大部分题我都只给一个伪代码)。Anyway,请勿直接复制黏贴代码,小学期的作业也是要查重的,一旦被查到代码重复会严厉扣分,最好的方法是浏览一遍代码并且掌握相关的要领后自己手打一遍,同时也要做好总结和回顾的工作,这样才能高效地提升自己的代码水平。
加油!
成绩 | 10 | 开启时间 | 2021年09月3日 星期五 11:00 |
折扣 | 0.8 | 折扣时间 | 2021年09月10日 星期五 23:00 |
允许迟交 | 否 | 关闭时间 | 2021年10月10日 星期日 23:00 |
Description
又是北湖深坑,惊不惊喜,意不意外?!
Roark觉得用水填湖太没意思了,用石头填坑多有意思。
假设北湖的地面还是一维的,每一块宽度都为1,高度是非负整数,用一个数组来表示。
现提供不限量的规格的石头,问是否可以将北湖填平。(所有地面到达同一高度即为填平)
注:石头只能水平或垂直填放。
Input
样例有多组输入至文件末尾;
每组用例占两行;
第一行输入1个整数 表示北湖地面总宽度;
第二行输入n个数 ,用空格间隔,表示地面高度。
Output
若能填平则输出“YES”,否则输出“NO”。
测试用例 1 | 以文本方式显示
| 以文本方式显示
| 1秒 | 64M |
题意分析:
考查优化策略的一道题。
对于这种既能横放又能竖放的,一通瞎操作随便放肯定不行,暴力搜索也肯定不行,所以必然有优化方法。既然每个地方都给出了“高度”,那这个图像就跟俄罗斯方块差不多——唯一的区别就是,不会出现上面有顶下面有底而中间是空的情况。玩俄罗斯方块你最喜欢啥呀?一定是那个1 4的棍子,因为他完全不用考虑地形如何,只要竖着放不碰到顶,最起码这一步是没有危险的(没有形成中空区域的风险)。于是这道题我们也可以类似的思考,既然他没说要我们用最少的石头来填,那我们就可劲填,先用竖着的12方块把每个地方都填到“近似”相同高度为止。
不难用数学证明出来,这样填完之后的结果,一定是像“锯齿”一样的序列,高度极差最多为1,如下图所示:
这样,其实整个信息就被简化为了一个01序列,我们要研究的就是,当这个01序列满足什么样的性质的时候,它能够被完全的填平。
首先我们先看这个01序列本身有什么性质吧,最重要的一点,是如果对这个序列各位取反,和这个序列本身是等价的,这个的证明非常显而易见,我们只要把每个“0”的位置上竖着放一个 12方块,它就变成了2,于是每个0都变成了2,每个1都不变,如果全体减一,相当于对原本那个01序列取反。
如果这个序列中出现了相邻的0或者相邻的1,那在我们眼里是再好不过的事,因为这样他们就可以水平地放置 21的方块,这样高度就可以以1位单位增加——换句话说,想叠到什么高度,就能叠到什么高度,因此如果遇到了这样的子段,我们完全可以不管它。
但是“不管”也分情况,是直接当这俩不存在呢,还是在遍历的时候跳过呢?我们就要研究另一种情况,即类似1001这样的序列——如果直接当这俩不存在,那么00消去,11也变成了相邻的序列,也能消去,这样可行吗?答案是肯定的,因为我们一旦把中间填上一个21的水平方块,整个序列就变成了了1111,也就是0000,那么就是两组相邻的0,自然可以消去。
类似的,我们可以证明一个结论,每当出现相邻的0或者相邻的1时,我们都可以直接消去。这叫什么呀?这就是栈顶消去呀,这就是后进先出LIFO呀,那用个栈就非常的水到渠成了。
于是,到目前为止的思路就出来了,参见下方伪代码。(当然,这个伪代码有非常多可以优化的空间,有余力的同学可以自己思考一下)
伪代码:
读入数据组数,按组循环:
长度为n的循环:
读入数据,将每个数据&1,得到这个数据的二进制编码;
//想一想,&1是什么意思
二进制编码入栈;
循环条件:如果栈顶有两个相同编码
连续弹出栈顶两次
如果最后栈为空或栈大小为1,输出YES,否则输出NO;
//想一想,为什么栈为1也可以
贴代码:
#include <bits/stdc++.h>
#define pb push_back
#define pf push_front
#define __MAX 100010
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
typedef pair<int, int> pii;
typedef stack<int> stk;
typedef unordered_map<int, int> umi;
typedef unordered_set<int> usi;
const int INF = 0x3f3f3f;
const double EPS = 1e-8;
const double PI = acos(-1);
int h[200010];
int c = 0;
int main(){
///ifstream infile("input.txt", ios::in);
///ofstream outfile("output.txt", ios::out);
int width;
while(cin >> width){
int max = 0;
for(int i = 0; i < width; i++){
scanf("%d", &h[i]);
if(h[i] > max)
max = h[i];
}
for(int i = 0; i < width; i++){
if((max - h[i]) % 2 == 0) //这里不要学我这么写!!非常的慢!直接位运算就行
h[i] = 0;
else
h[i] = 1;
}
stk s;
for(int i = 0; i < width; i++){
if(s.empty()){
s.push(h[i]);
} else{
if(s.top() == h[i])
s.pop();
else{
s.push(h[i]);
}
}
}
if(s.size() <= 1)
cout << "YES" << endl;
else
cout << "NO" << endl;
}