B-咕咕东想吃饭(贪心算法)
一、题目描述
咕咕东考试周开始了,考试周一共有n天。他不想考试周这么累,于是打算每天都吃顿好的。他决定每天都吃生煎,咕咕东每天需要买aia_iai个生煎。但是生煎店为了刺激消费,只有两种购买方式:
①在某一天一次性买两个生煎。
②今天买一个生煎,同时为明天买一个生煎,店家会给一个券,第二天用券来拿。
没有其余的购买方式,这两种购买方式可以用无数次,但是咕咕东是个节俭的好孩子,他训练结束就走了,不允许训练结束时手里有券。咕咕东非常有钱,你不需要担心咕咕东没钱,但是咕咕东太笨了,他想问你他能否在考试周每天都能恰好买aia_iai个生煎。
输入格式
输入两行,第一行输入一个正整数n(1<=n<=100000)(1<=n<=100000)(1<=n<=100000),表示考试周的天数。
第二行有n个数,第i个数ai(0<=ai<=10000)a_i(0<=a_i<=10000)ai(0<=ai<=10000)表示第i天咕咕东要买的生煎的数量。
输出格式
如果可以满足咕咕东奇怪的要求,输出"YES",如果不能满足,输出“NO”。(输出不带引号)
样例输入1
4
1 2 1 2
样例输出1
YES
样例输入2
3
1 0 1
样例输出2
NO
数据规模
数据点 n(上限) aia_iai(上限)
1,2 10 10
3,4,5 1000 10
6,7 10 10000
8,9,10 100000 10000
二、思路与算法
选用贪心算法,想要每天吃到一定数量的生煎,那么某天如果要吃偶数个生煎,就全选方案1,奇数个,选方案二,原因是什么呢?
因为本题目的是考察某种安排是否能够实现,并不需要求最优解或者其他。
同时,安排是否能实现,只与每天生煎数的奇偶有关,若想让一个奇数变偶,1足够了,2、4、6等偶数反而没用,3、5、7等奇数和1效果是一样的(如果1不行,3、5、7等也不行)。
所以,出现了上述贪心策略,而不需要去遍历所有可能性(这样的dfs相当于根本没有剪枝)。
三、代码实现
一开始在csp模考中,我想的算法是dfs搜索(以前都没有根据数据判断算法可不可用的意识),结果显然超时,所以这个代码不一定对,因为只是前几个点ac,后面可能有错误没机会报出来。
//dfs方法 数据太多 会超时
#include<iostream>
#include<vector>
using namespace std;
int n=0;
vector<int> a(0);
int flag=0;
void solution(int i,int num){
if(i>n-1||num<0){return;}
if(i==n-1){
if(num%2==1){return;}
else{flag=1; return;}
}
else{
int n=num/2;
for(int k=0;k<=n;k++){
solution(i+1,a[i+1]-(num-2*k));
}
}
return;
}
int main(){
scanf("%d",&n);
int temp=0;
for(int i=0;i<n;i++){
scanf("%d",&temp);
a.push_back(temp);
}
solution(0,a[0]);
if(flag==1){cout<<"YES\n";}
else{cout<<"NO\n";}
return 0;
}
之后一直超时,询问学长才知道,一看这个数据规模就应该排除搜索…
所以本题选用的是贪心算法。
#include <cstdio>
//贪心算法
int main(){
int n=0,temp=0,flag=0;//标记此时是否有券
scanf("%d",&n);
int a[n];
for(int i=0;i<n;i++){
scanf("%d",&a[i]);
}
for(int i=0;i<n;i++){
if(a[i]%2==0){
if(flag==0){continue;}
else{flag=1; continue;}
}
else{
if(flag==0){flag=1; continue;}
else{flag=0; continue;}
}
}
if(flag==1){printf("NO\n");}
else{printf("YES\n");}
return 0;
}
四、经验与总结
- 一定一定!!想算法前要先看数据规模!数据规模很大的,绝对不要想n^2及以上时间复杂度的算法!dfs、bfs不进行记忆性剪枝,更不要想!
- 看待问题一定要更深层次!不能看完表面,就想算法,就开始实现。算法最根本,算法如果错了,后续所有实现都是在做无用功。
- 再次提醒:输入输出用scanf和printf!