列表

详情


NC19884. [AHOI2009]CHECKER

描述

在一个1行N列(N是奇数)的棋盘上,有K个格子是红色的。这种情况下,你有一个跳棋在最左端的格子上。你的目标是将它移动到最右边的格子,在开始移动之间,你可以在棋盘的任意空位上放棋子。在游戏开始后 你只可以随时在一个红色格子上放棋子。棋子的移动规则是:每次只可以选择一个棋子,跳过与之相邻的棋子走到后面的空格上,被它跳过的棋子被吃掉,即从棋盘上移走,如相邻棋子的另一侧有棋子,则不能跳。
请回答以下两个问题: 
1:移动开始前至少要放多少棋子才能完成任务。 
2:如果要使开始前放的棋子数要求尽量少,那么在移动过程中最少需要放多少个棋子才能完成任务。 
关于规则的补充说明: 
1:只能往空位上放棋子,不管是移动开始前还是移动过程中。 
2:移动前棋盘最左端的那个原始棋子绝对不能被吃掉.

输入描述

第一行一个正奇数N
第二行有N个整数,如果第i个整数是非功过,说明第i个格子是红棋,否则为白棋,数字间用空格分开.

输出描述

两个数字分别代表第一问和第二问的结果.

示例1

输入:

5
0 0 0 1 0

输出:

1
1

说明:

在游戏开始前,可以在第二个格子上放上一个棋子,游戏开始后可用最左边的棋子吃掉它,从而移动到第三格。然后由于第四格是个红色的格子,在游戏中可以在那放一个棋子,然后用已经移动第三格的棋子把它吃掉,从而达到终点。

原站题解

上次编辑到这里,代码来自缓存 点击恢复默认模板

C++11(clang++ 3.9) 解法, 执行用时: 12ms, 内存消耗: 1272K, 提交时间: 2019-12-30 19:50:42

#include<bits/stdc++.h>
#define ll long long
using namespace std;
ll n,i,ans,f[100010],a[100010],flag,c[2];
int main(){
	scanf("%lld",&n);
	for(i=1;i<=n;i++)scanf("%lld",&a[i]);
	for(i=3;i<=n;i++)if(a[i]&&a[i-1])flag=1;
	if(!flag){
		for(i=2;i<=n;i+=2)c[a[i]]++;
		printf("%lld\n%lld",c[0],c[1]);
		return 0;
	}
	memset(f,44,sizeof(f));
	for(i=2;i<=n;i++)if(a[i])f[i]=1;
	for(i=3;i<=n;i++)f[i]=min(f[i],f[i-1]+f[i-2]);
	for(i=n;i>=2;i--)f[i]=min(f[i],f[i+1]+f[i+2]);
	for(i=2;i<=n;i+=2)ans+=f[i];
	printf("0\n%lld",ans);
}

上一题