UVA 10317 - Equating Equations 贪心 dfs

UVA 10317 - Equating Equations 贪心 dfs

ACM

题目地址:UVA 10317 - Equating Equations

题意: 
给一个等式,但是这个等式不一定是正确的,要你对等式中的数字重新排序,使得等式成立。等式只有+和-,数字个数小于16。

分析: 
a + b - c = d - e为例子。 
1. 我们把等式右边的各项都换到左边,a + b - c - d + e = 0 
2. 把+项和-项放一起,就变成(a + b + e) - (c + d) = 0 
3. 然后(a + b + e) = (c + d) 
4. 所以所有数字的和sum应该为偶数,然后我们只要找到多少个-项,dfs找到同样多的数,且和正好是sum / 2,那等式就能成立了。 
5. 然后输出就是手工问题了。

代码

/*
*  Author:      illuz <iilluzen[at]gmail.com>
*  File:        10317.cpp
*  Create Date: 2014-06-27 14:52:46
*  Descripton:  brute force 
*/

#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
using namespace std;

const int N = 100;

bool pom[2][N];	// plus or minus, 0 is plus, 1 is minus
int lterm, rterm;
char eqt[N];
int sum, num[N], cnt, mcnt;
bool choose[N];

void init() {
	char tmp[4];
	int len = strlen(eqt), prev = 0, dpom = 0, npom = 0;
	cnt = 0;
	mcnt = 0;
	sum = 0;
	for (int i = 0; i < len; ) {
		sscanf(eqt + i, "%s", tmp);
		if (tmp[0] == '+') {
			pom[dpom][npom++] = 0;
			prev = 0;
		} else if (tmp[0] == '-') {
			pom[dpom][npom++] = 1;
			prev = 1;
		} else if (tmp[0] == '=') {
			dpom++;
			lterm = npom;
			npom = 0;
			prev = 0;
		} else {
			mcnt += dpom ^ prev;
			sscanf(tmp, "%d", &num[cnt]);
			sum += num[cnt];
			cnt++;
		}
		i += strlen(tmp) + 1;
	}
	rterm = npom;
}

bool dfs(int restsum, int pos, int restcnt) {
	if (restcnt == 0)
		return restsum == 0;
	if (restsum < 0 || restcnt < 0)
		return false;
	for (int i = pos; i <= cnt - restcnt; i++) {
		choose[i] = 1;
		if (dfs(restsum - num[i], i + 1, restcnt - 1))
			return true;
		choose[i] = 0;
	}
	return false;
}

bool solve() {
	memset(choose, 0, sizeof(choose));
	if (sum % 2) {
		return false;
	}
	return dfs(sum / 2, 0, mcnt);
}

void print() {
	int p[N], m[N], pcnt = 0, mcnt = 0;
	for (int i = 0; i < cnt; i++) {
		if (choose[i]) {
			m[mcnt++] = num[i];
		} else {
			p[pcnt++] = num[i];
		}
		// cout << choose[i] << ' ';
	}

	printf("%d", p[--pcnt]);
	for (int i = 0; i < lterm; i++) {
		if (pom[0][i] == 0) {
			printf(" + %d", p[--pcnt]);
		} else {
			printf(" - %d", m[--mcnt]);
		}
	}

	printf(" = %d", m[--mcnt]);
	for (int i = 0; i < rterm; i++) {
		if (pom[1][i] == 1) {
			printf(" - %d", p[--pcnt]);
		} else {
			printf(" + %d", m[--mcnt]);
		}
	}
	puts("");
}

int main() {
	while (gets(eqt)) {
		init();
		if (solve()) {
			print();
		} else {
			puts("no solution");
		}
	}
	return 0;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值