[Advanced] (2016-11-16) 黑白棋

一条线上的黑白棋游戏,放下一个棋子时,与已有的己方棋子所夹的无间隙的敌方棋子会全部变成己方。如果到边界全是敌方棋子也要吃掉
位置的数量N(N<=30)给出,初始状态给出,0空白1黑子2白子
程序控制下黑棋,白棋每次固定放在所有空位中最左边的位置
黑先白后,走3步
求最后黑棋最多多少个



输入:
用例数T
N
N个位置的初始状态


输出:最大黑棋数量
DFS

由于这道题走出去的一步无法根据走的那步还原到走之前的状态,所以不能使用全局的标记数组完成回溯,得在dfs函数中传递局部变量
注意吃掉地方棋子时,需要向两个方向判断,不能有空位置。另外边界的处理和普通的黑白棋不同
5


15
0 2 2 0 1 2 2 1 0 0 0 0 2 0 2


15
1 2 2 0 2 2 2 2 0 0 0 2 0 0 1


15
2 1 1 0 0 1 1 0 0 1 1 0 0 1 2


15
1 1 1 0 0 1 1 0 0 1 1 0 0 1 1


15
2 1 1 0 0 1 1 0 0 1 0 0 0 1 2
0: 2 2 2 2 2 2 2 2 2 2 2 2 2 0 2
1: 1 2 2 2 2 2 2 2 2 2 2 2 2 0 2
3: 1 2 2 2 2 2 2 2 2 2 2 0 2 1 1
4: 1 2 2 2 2 2 2 2 2 2 1 0 2 1 1
5: 1 2 2 2 2 2 2 2 2 2 0 1 1 1 1
6: 2 2 2 1 1 2 2 2 2 2 0 1 1 1 1
7: 1 1 1 1 1 2 2 2 2 2 2 0 2 1 1
8: 1 1 1 1 1 2 2 2 2 2 1 0 2 1 1
9: 1 1 1 1 1 2 2 2 2 2 0 1 1 1 1
#1 9
0: 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2
4: 1 1 1 1 2 2 2 2 2 2 2 2 2 2 2
7: 1 1 1 1 2 2 2 2 2 2 2 2 1 1 1
11: 1 1 1 1 1 1 1 1 1 1 1 2 2 2 2
#2 11
0: 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2
#3 0
0: 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2
#4 0
1: 2 2 2 2 2 2 2 2 2 2 2 2 0 1 2
2: 2 2 2 2 2 2 2 2 2 2 2 1 0 1 2
4: 2 2 2 2 2 2 2 2 2 1 1 1 0 1 2
5: 2 2 2 2 2 2 2 2 1 1 1 1 0 1 2
#5 5
#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>

int T, N, init[30], answer;

int *getArrayCopy(int *src) {
	int *copy = new int[N];
	for (int i = 0; i < N; i++) {
		copy[i] = src[i];
	}
	return copy;
}

int calcResult(int *chess){
	int result = 0;
	for (int i = 0; i < 30; i++) {
		if (chess[i] == 1){
			result++;
		}
	}
	return result;
}

void turnOver(int *chess, int position, int type){
	int opposition = type == 1 ? 2 : 1;
	int left = position;
	int right = position;

	for (int i = position - 1; i >= 0; i--) {
		if (i == 0){
			if (chess[i] == 0){
				left = position;
			}
			else {
				left = 0;
			}
		}
		else {
			if (chess[i] == opposition){
				left = i;
			}
			else if (chess[i] == type){
				break;
			}
			else {
				left = position;
				break;
			}
		}
	}

	for (int i = position + 1; i < N; i++) {
		if (i == N - 1){
			if (chess[i] == 0){
				right = position;
			}
			else{
				right = N - 1;
			}
		}
		else {
			if (chess[i] == opposition){
				right = i;
			}
			else if (chess[i] == type){
				break;
			}
			else {
				right = position;
				break;
			}
		}
	}

	for (int i = left; i <= right; i++) {
		chess[i] = type;
	}
}

void whiteStep(int *chess){
	for (int i = 0; i < N; i++) {
		if (chess[i] == 0){
			chess[i] = 2;
			turnOver(chess, i, 2);
			return;
		}
	}
}

void printResult(int *chess){
	for (int i = 0; i < N; i++) {
		printf("%d ", chess[i]);
	}
	printf("\n");
}

void dfs(int *chess, int steps){
	if (steps == 3){
		int result = calcResult(chess);
		if (answer < result){
			printf("%d: ", result);
			printResult(chess);
			answer = result;
		}
		return;
	}

	for (int i = 0; i < N; i++) {
		if (chess[i] == 0){
			int *chessCopy = getArrayCopy(chess);
			chessCopy[i] = 1;
			turnOver(chessCopy, i, 1);
			whiteStep(chessCopy);
			dfs(chessCopy, steps + 1);
		}
	}
}


int main(int argc, char** argv) {
	freopen("sample_input.txt", "r", stdin);
	setbuf(stdout, NULL);

	scanf("%d", &T);
	for (int test_case = 1; test_case <= T; ++test_case){
		scanf("%d", &N);
		for (int i = 0; i < N; i++){
			scanf("%d", &init[i]);
		}

		answer = -1;
		dfs(init, 0);

		printf("#%d %d\n", test_case, answer);
	}
	return 0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值