uva 10317(回溯)

来源:互联网 发布:王尼玛淘宝店 编辑:程序博客网 时间:2024/06/07 15:47

题意:给出一个等式但等式两边不一定相等,要求把这些数和运算符重新组合成一个成立的等式输出,如果不可以输出no solution。

题解:将所有的数都一起移动到等号左边,然后统计需要加的数的个数plusnum,只有要加的数和要减的数之和是相等的才有解,那么所有数字的绝对值之和一定是偶数(因为x = x  ->  sum = 2x  ->  sum是偶数),然后就要回溯出相应的要加的数字都有哪些,如果选出要加的数字符合之前统计的数量plusnum且刚好数字和是sum / 2,那么就是有解的,把这些数字填到输入时统计的要加的数的位置,剩下的数字放到要减的位置就ok了。剪枝:回溯时如果加起来大于sum / 2就不必算了。


#include <stdio.h>#include <string.h>const int N = 1000;char str[N], ch[N];int sum, n, plusnum, num[N], flag, vis[N], res[N], plus[N];void read() {int len = strlen(str);sscanf(str, "%d", &num[0]);n = plusnum = 1;sum = num[0];for (int i = 1; i < len; i++) {if (str[i] == '+' || str[i] == '-' || str[i] == '=') {if (str[i] == '=')flag = n;ch[n] = str[i];sscanf(str + i + 1, "%d", &num[n]);sum += num[n++];}}for (int i = 1; i < n; i++)if (i < flag && ch[i] == '+')plusnum++;else if (i > flag && ch[i] == '-')plusnum++;}int dfs(int cur, int pos, int cnt) {if (plusnum - cur > n - pos)return 0;if (cur == plusnum) {if (cnt == sum / 2)return 1;return 0;}if (pos < n && (cnt + num[pos]) * 2 <= sum) {vis[pos] = 1;plus[cur] = num[pos];if (dfs(cur + 1, pos + 1, cnt + num[pos]))return 1;vis[pos] = 0;}if (pos < n && dfs(cur, pos + 1, cnt))return 1;return 0;}void solve() {memset(vis, 0, sizeof(vis));if (sum % 2 || (dfs(0, 0, 0) == 0)) {printf("no solution\n");return;}int k = 1;res[0] = plus[0];for (int i = 1; i < n; i++)if (i < flag && ch[i] == '+')res[i] = plus[k++];else if (i > flag && ch[i] == '-')res[i] = plus[k++];k = 1;for (int i = 0; i < n; i++)if (!vis[i]) {while (k < flag && ch[k] == '+' && k < n)k++;while (k > flag && ch[k] == '-' && k < n)k++;res[k++] = num[i];}printf("%d", res[0]);for (int i = 1; i < n; i++)printf(" %c %d", ch[i], res[i]);printf("\n");}int main() {while (gets(str)) {read();solve();}return 0;}

0 0
原创粉丝点击