P4753 River Jumping

题目大意

有一条宽度为\(N\)的河上,小D位于坐标为\(0\)的河岸上,他想到达坐标为\(N\)的河岸上后再回到坐标为\(0\)的位置。在到达坐标为\(N\)的河岸之前小D只能向坐标更大的位置跳跃,在到达坐标为\(N\)的河岸之后小D只能向坐标更小的位置跳跃。在河的中间有\(M\)个岩石,小D希望能跳到每个岩石上恰好一次。由于小D的跳跃能力太强,小D的跳跃长度有个下限\(S\),但没有上限。现在请你判断他是否能够完成他的目标。

思路

  1. 如果存在\(pos_{i+2}-pos_i < s\)则无解

  2. 如果存在\(pos_1-pos_0 < s\)或\(pos_{m+1}-pos_m < s\)则无解

  3. 在跳跃时,若\(pos_{i+1}-pos_i < s\),则跳到\(pos_{i+2}\)。

  4. 在跳跃时,若\(pos_{i+1}-pos_i \ge s\)且\(pos_{i+1}, pos{i+2}, pos{i+3}\)中,相邻两个距离均\(< s\),则跳到\(pos_{i+2}\)

代码

int main(){
	m=read(); n=read(); s=read();
	for(int i=1;i<=n;i++)a[i]=read();
	a[0]=0; a[++n]=m; a[n+1]=999999; a[n+2]=9999999;
	
	// check possibility
	// part - 1
	for(int i=0;i<=n-2;i++){
		if(a[i+2]-a[i]<s){
			ok=0; break;
		}
	}
	// part - 2
	if(a[1]-a[0]<s||a[n]-a[n-1]<s)ok=0;
	
	if(ok==0){
		cout<<"NO"<<endl;
		return 0;
	}
	
	// solve
	int pos=0;
	while(pos!=n){
		if(a[pos+1]-a[pos]>=s){
			if(a[pos+3]-a[pos+2]<s&&a[pos+2]-a[pos+1]<s){
				pos=pos+2;
			}
			else pos++;
		}
		else pos+=2;
		v[pos]=1;
		ans[++ans[0]]=pos;
	}
	for(int i=n;i>=0;i--){
		if(v[i])continue;
		ans[++ans[0]]=i;
	}
	printf("YES\n");
	for(int i=1;i<=ans[0];i++){
		printf("%d ",ans[i]);
	}
	return 0;
}
上一篇:字符串可以 按数组格式输出单字符


下一篇:Mysql安装和命令使用