codeforces 1428 D. Bouncing Boomerangs (贪心)

题目链接:https://codeforces.com/contest/1428/problem/D


首先发现贪心策略: 对于当前列 1. 如果路径有一个动物,意味着这个列上有一个动物,那尽量向上放一定是最优的 2. 若路径上有两个动物,意味着除了这个列上有一个动物,该行也需要有一个动物,
则需要从之后的列找到路径上只有一个动物的列进行占领 3. 若路径上有三个动物,则需要对后面相离最近的可占领的列进行占领
具体实现细节看代码 需要一点码力 ```c++ #include #include #include #include #include #include #include using namespace std; typedef long long ll;

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;

}

posted @ 2020-10-19 20:32  Tartarus_li  阅读(196)  评论(0编辑  收藏  举报