B. Game of the Rows(贪心)
题意:
有k种颜色,每种有(a_i)个,将这k种颜色放在一个(n * 8格子里)
放置规则不能出现两个不同颜色在相邻的格子里,相邻的定义为在同一行
出现在(1,2),(3,4),(4,5),(5,6)或者(7,8) 这样都算相邻
(1 <= n <= 10000)
(a_i <= 1000)
$ sum a_i <= 8 * n$
思路:
这道题贪心很不错,我是yy了很久了
贪心策略应该是让每种颜色尽量填满中间,再填满两边,
然后再把三个的放到中间,放不下就放到两边,
再把两个的放到中间,最后再填一个的
#include<bits/stdc++.h>
#define LL long long
#define lson l,m,rt<<1
#define rson m+1,r,rt<<1|1
#define ls (rt<<1)
#define rs (rt<<1|1)
using namespace std;
const int N = 1e6 + 10;
const int M = 1e6 + 10;
const int mod = 1e9 + 7;
int a[1100];
void can(int &x,int &y,int d){
if(!x || y < d) return ;
int res = min(x, y / d);
x -= res;
y -= res * d;
}
int main(){
int n,k;
cin>>n>>k;
int cnt2 = 2 * n,cnt4 = n;
for(int i = 0;i < k;i++){
scanf("%d",a + i);
}
for(int i = 0;i < k;i++){ ///首先尽量填满中间,然后填满两边
can(cnt4,a[i],4);
can(cnt2,a[i],2);
if(a[i] && (!cnt2 && !cnt4)) {
puts("NO");
return 0;
}
}
int c[4] = {0};
for(int i = 0;i < k;i++) c[a[i]]++;
int res3 = min(cnt4,c[3]);///把 3的 尽量放中间
c[3] -= res3;
cnt4 -= res3;
if(2 * c[3] > cnt2){ ///剩下的3 只能放两边了
puts("NO");
return 0;
}
cnt2 -= 2 * c[3];
int res2 = min(cnt4,c[2]); ///将 2 个的 放在中间的 剩余一个位置可以放其他
c[2] -= res2;
cnt4 -= res2;
if(2 * c[2] + c[1] <= res2 + cnt4 * 2 + cnt2) puts("YES");///计算所有能放一个的不同位置的个数
else puts("NO");
return 0;
}