[Advanced] (2016-09-21) 加油站

有两种加油站,分别适合给其相对应的汽车加油。
两个加油站之间,直线排列着N(N<=8)辆汽车等待加油,汽车可能是任意一种,相距都是1
一个加油机器人从加油站携带汽油给汽车加。机器人每次可以携带2辆汽车油箱需要的汽油,从某种加油站携带的有只能给给对应的汽车加,携带的汽油可以丢弃。机器人从左边的加油站出发
求加油机器人给所有的汽车加满油所需要移动的最短距离


输入:
用例数T
N
N个汽车的类型(1代表左边,2代表右边)


输出:加油机器人的最短距离

6


3
2 1 2


5
1 2 1 2 1


6
2 2 1 1 1 1


8
1 1 1 1 2 2 2 2


8
2 2 2 2 1 1 1 1


8
2 2 2 2 2 2 2 1
#1 7
#2 12
#3 18
#4 21
#5 33
#6 41
#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>

int T, N, answer;
bool cars[8], flag[8];

void dfs(int position, bool gasType, int gasCount, int distance, int finished){
	if (distance >= answer){
		return;
	}

	if (finished == N){
		if (answer > distance){
			answer = distance;
		}
		return;
	}

	if (gasCount == 2){
		for (int i = 0; i < N; i++){
			if (cars[i] == gasType && !flag[i]){
				flag[i] = true;
				int distanceIncrease = i > position ? i - position : position - i;
				dfs(i, gasType, 1, distance + distanceIncrease, finished + 1);
				flag[i] = false;
			}
		}
	}
	else {
		if (gasCount == 1){
			if (!gasType){
				for (int i = position + 1; i < N; i++){
					if (cars[i] == gasType && !flag[i]){
						flag[i] = true;
						dfs(i, gasType, 0, distance + i - position, finished + 1);
						flag[i] = false;
					}
				}
			}
			else{
				for (int i = position - 1; i >= 0; i--){
					if (cars[i] == gasType && !flag[i]){
						flag[i] = true;
						dfs(i, gasType, 0, distance + position - i, finished + 1);
						flag[i] = false;
					}
				}
			}
		}
		dfs(-1, false, 2, distance + position + 1, finished);
		dfs(N, true, 2, distance + N - position, finished);
	}
}

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);
		answer = 72;
		for (int i = 0; i < N; i++){
			int car;
			cars[i] = false;
			flag[i] = false;
			scanf("%d", &car);
			if (car == 2){
				cars[i] = true;
			}
		}

		dfs(-1, false, 2, 0, 0);

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

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值