题目
思路
感谢@薄层 的博客提供了思路。
如果一组士兵的数量不小于四,那么就想办法让他们坐在某个长度为四的位置上。
如果没有位置了,就用两个长度为二的来凑。
经过这一轮处理之后,没有人能够坐满长度为四的座位了,一定会空出来至少一个位置。
所以一个长度为四的,就变成了一个长度为二的,和一个长度为一的。
接下来暴力做即可。优先用长度为二的(只要士兵的剩余数量不小于二)。
最后进行一次微调。
- 如果长度为一的,用的太多,就用长度为二的去填补,一个只能换一个。
- 如果长度为二的,用的太多,就用长度为一的去填补,两个换来一个。
判断是否二者都非负即可。
代码
#include <cstdio>
#include <iostream>
#include <vector>
#include <algorithm>
#include <cmath>
using namespace std;
inline int readint(){
int a = 0; char c = getchar(), f = 1;
for(; c<'0' or c>'9'; c=getchar())
if(c == '-') f = -f;
for(; '0'<=c and c<='9'; c=getchar())
a = (a<<3)+(a<<1)+(c^48);
return a*f;
}
inline void writeint(long long x){
if(x < 0) putchar('-'), x = -x;
if(x > 9) writeint(x/10);
putchar((x%10)^48);
}
# define MB template < class T >
MB void getMax(T &a,const T &b){ if(a < b) a = b; }
MB void getMin(T &a,const T &b){ if(b < a) a = b; }
const int MaxN = 10005;
int a[MaxN];
int main(){
int k = readint(), n = readint();
for(int i=1; i<=n; ++i)
a[i] = readint();
int one = 0, two = k<<1, four = -k;
for(int i=1; i<=n; ++i)
four += a[i]>>2, a[i] &= 3;
if(four >= 0) two -= four<<1;
else two += (one = -four);
for(int i=1; i<=n; ++i)
two -= (a[i]&2)>>1, one -= (a[i]&1);
if(two < 0 and one < 0)
return puts("NO")*0;
if(two < 0) one += two*2, two = 0;
if(one < 0) two += one, one = 0;
puts(two >= 0 and one >= 0 ? "YES" : "NO");
return 0;
}