codeforces 1428 D. Bouncing Boomerangs (贪心)
题目链接:https://codeforces.com/contest/1428/problem/D
首先发现贪心策略: 对于当前列 1. 如果路径有一个动物,意味着这个列上有一个动物,那尽量向上放一定是最优的 2. 若路径上有两个动物,意味着除了这个列上有一个动物,该行也需要有一个动物,
则需要从之后的列找到路径上只有一个动物的列进行占领 3. 若路径上有三个动物,则需要对后面相离最近的可占领的列进行占领
具体实现细节看代码 需要一点码力 ```c++ #include
const int maxn = 200010;
int n,cnt,flag;
int a[maxn],oc[maxn],fr[maxn],ty[maxn];
int x[maxn],y[maxn],pos[maxn],p2[maxn];
ll read(){ ll s=0,f=1; char ch=getchar(); while(ch<'0' || ch>'9'){ if(ch=='-') f=-1; ch=getchar(); } while(ch>='0' && ch<='9'){ s=s10+ch-'0'; ch=getchar(); } return sf; }
int main(){
cnt = 0, flag = 0;
memset(oc,0,sizeof(oc));
n = read();
for(int i=1;i<=n;++i) a[i] = read();
for(int i=n-1;i>=1;--i){
if(a[i+1] == 1) pos[i] = i+1;
else{
pos[i] = pos[i+1];
}
}
for(int i=n-1;i>=1;--i){
if(a[i+1]!=0) p2[i] = i+1;
else{
p2[i] = p2[i+1];
}
}
// for(int i=1;i<=n;++i) printf("%d ",pos[i]); printf("\n");
for(int i=1;i<=n;++i){
if(!a[i]) continue;
if(!oc[i]){ // 路径没被占领
if(a[i] == 1){
fr[i] = i;
++cnt;
x[cnt] = fr[i], y[cnt] = i;
}
if(a[i] == 2){
fr[i] = i;
++cnt;
x[cnt] = fr[i], y[cnt] = i;
int p = pos[i];
while(oc[p]) p = pos[p]; // 向后找能放置的位置 (只有 a[i] = 1 的位置能放置)
if(!p){
flag = 1; // 找不到这个位置
break;
}
oc[p] = i; ty[p] = 2;
}
if(a[i] == 3){
fr[i] = i;
++cnt;
x[cnt] = fr[i], y[cnt] = i;
int p = p2[i];
while(oc[p]) p = p2[p]; // 向后找能放置的位置 (a[i] = 1, a[i] = 2 的位置都能放置)
if(!p){
flag = 1; // 找不到这个位置
break;
}
oc[p] = i; ty[p] = 3; // 位置被占领 2 个
}
}else{
if(a[i]==1){
if(ty[i] == 2){
fr[i] = oc[i];
++cnt;
x[cnt] = fr[i], y[cnt] = i;
}
if(ty[i] == 3){
fr[i] = oc[i];
++cnt;
x[cnt] = fr[i], y[cnt] = i;
if(fr[i] + 1 <= n){
++cnt;
x[cnt] = fr[i] + 1, y[cnt] = i;
}else{
flag = 1;
break;
}
}
}
if(a[i] == 2){
fr[i] = oc[i];
++cnt;
x[cnt] = fr[i], y[cnt] = i;
if(fr[i] + 1 <= n){
++cnt;
x[cnt] = fr[i] + 1, y[cnt] = i;
}else{
flag = 1;
break;
}
int p = pos[i];
while(oc[p]) p = pos[p]; // 向后找能放置的位置 (只有 a[i] = 1 的位置能放置)
if(!p){
flag = 1; // 找不到这个位置
break;
}
oc[p] = fr[i] + 1; ty[p] = 2;
}
if(a[i] == 3){
fr[i] = oc[i];
++cnt;
x[cnt] = fr[i], y[cnt] = i;
if(fr[i] + 1 <= n){
++cnt;
x[cnt] = fr[i] + 1, y[cnt] = i;
}else{
flag = 1;
break;
}
int p = p2[i];
while(oc[p]) p = p2[p]; // 向后找能放置的位置 (a[i] = 1, a[i] = 2 的位置都能放置)
if(!p){
flag = 1; // 找不到这个位置
break;
}
oc[p] = fr[i] + 1; ty[p] = 3; // 位置被占领 2 个
}
}
}
if(flag){
printf("-1\n");
}
else{
printf("%d\n",cnt);
for(int i=1;i<=cnt;++i){
printf("%d %d\n",x[i],y[i]);
}
}
return 0;
}