填坑 I
题目描述
解题思路
这题我们可以先自己举个例子找找思路:假设宽度为6,位置从左向右依次是1至6。不难可以发现如果3、4高度相等,那么我们可以在此处任意个2×1石头块使其到达我们任意想要的高度。对于相邻的2、5处,如果高度相差2的倍数(或者说奇偶性相同)我们可以在这两处放置1×2石块以及在3、4处放置2×1石块,使2、3、4、5处高度相同。之后我们对于1、6处也可类似处理。
显然,在我们举的例子中,位置3比位置1、2后输入,却最先和位置4配对好,这符合栈后进先出的特点。因此,这题我们可以用栈来实现。
经过我们的分析,可以看到,假定我们输入一个数据a(a 表示 i 位置的高度),如果栈非空并且a与栈顶元素的奇偶性相同(此处我们可以让a&=1,这样奇数会变成1,偶数会变成0, 都转化成0、1来比较),那么我们我们让栈顶元素出栈,否则我们让a入栈。
当我们处理完所有数据后,显然如果栈空或者栈内只有一个元素,则说明最终可以填平。
代码实现
#include <iostream>
#include <stack>
using namespace std;
stack<int> stk;
int main()
{
int n,a;
while(~scanf("%d",&n))
{
while(!stk.empty()) stk.pop();
for(int i=1;i<=n;i++)
{
scanf("%d",&a);
a&=1;
if(!stk.empty() && a==stk.top()) stk.pop();
else stk.push(a);
}
if(stk.empty() || 1==stk.size()) printf("YES\n");
else printf("NO\n");
}
return 0;
}
填坑 II
题目描述
解题思路
有了上一题做基础,我们很容易看出这一题仍然是用栈来实现。因为本题只能用2×1的石块,所以不同于上一题相邻的两处只要奇偶性相同便可以配对,本题严格要求相邻两处高度相同方可配对。
此外,本题和上一题还有一些不同:
- 如果当前输入的元素大于栈顶元素,不难想象到栈顶元素无法与后面高度相等的元素配对(说的形象点就是中间有高处挡住了,比如2 4 4 2 这种),因此我们便可以认为无法填平,终止操作了。
- 在结束数据输入后,如果栈内只有一个元素,那么这个元素必须是所有输入元素中最大的,这样才能填平。举个反例:4 2 2 4 1 ,显然前面四个高度要到4才可填平,但是最右边的高度是无法上升的。
代码实现
#include <iostream>
#include <stack>
using namespace std;
stack<int> stk;
int main()
{
int n,a;
while(~scanf("%d",&n))
{
while(!stk.empty()) stk.pop();
int max=0;
bool flag=true;
for(int i=1;i<=n;i++)
{
scanf("%d",&a);
if(flag)//flag=true表示有可能填平
{
if(a>max) max=a;
if(!stk.empty() && a>stk.top())
{
flag=false;//如果a大于当前栈顶值,不可能填平
}
else if(!stk.empty() && a==stk.top())
{
stk.pop();
}
else
{
stk.push(a);
}
}
}
if(stk.empty()) printf("YES\n");
else if(stk.size()==1 && stk.top()==max) printf("YES\n");
else printf("NO\n");
}
return 0;
}
后记
有人说 II 比 I 要简单得多,我却认为这两题各有千秋。这一题可能要更加形象,例子更容易举,不过考虑要更全面,分的情况要稍多一些。
最后,对于这种有多组数据输入的题目,建议大家一定要养成定义变量时初始化的好习惯,反复使用一个栈时,每次使用前也不要忘了清空(QAQ)
还有一个小方法,可以输入两次相同数据,如果输入结果不同,那肯定因为没有清空或忘记初始化导致的。