UVA10317- Equating Equations(回溯+剪枝)

本文介绍了一种算法,用于将给定的数学表达式通过重新排列数字的位置,使其成为等式。该算法首先判断表达式能否形成等式,如果可以,则通过将等号右边的数移动到等号右边,简化表达式,进一步确定所有数的和必须为偶数。接着,算法通过递归搜索方法找出符合条件的数组合,最终输出一种可能的等式形式。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

题目链接

题意:给出一个式子,但这个式子不一定是等式,在‘+’,‘-’,‘=’符号位置不变的情况下,重新排列数字的位置,使其成为等式,如果可以的话,输出其中一种排列方式。

思路:我们将等号右边的数全部移动到等号右边,例如a+b-c=d-e,移动后变成a+b+e-(c+d)=0,也就是a+b+e=c+d,所以当式子可以变化成等式时,所有数的和必然是偶数。那么问题可以转化为在n个数中找出m个数(m的值为等号左边的整数的数量),使m个 数的和为从和的一半。

代码:

#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>

using namespace std;

const int MAXN = 1005;

char str[MAXN], Lsy[MAXN], Rsy[MAXN], vis[MAXN];
int arr[MAXN], front[MAXN], back[MAXN];
int cnt1, cnt2, eql, Lnum, ans, flag, L, R;

int init() {
    cnt1 = 1, cnt2 = eql = L = R = 0;
    int l = strlen(str), sum = 0; 
    sscanf(str, "%d", &arr[0]);
    sum = arr[0];
    for (int i = 0; i < l; i++) {
        if (str[i] == '+' || str[i] == '-' || str[i] == '=') {
            if (str[i] == '=')
                eql = i;
            if (!eql) {
                Lsy[L] = str[i];
                L++;
            }
            else if (eql != i) {
                Rsy[R] = str[i];
                R++;
            }
            sscanf(str + i + 1, "%d", &arr[cnt1]);
            sum += arr[cnt1++];
        } 
    }

    Lnum = 1;
    for (int i = 0; i < l; i++) {
        if (i < eql && str[i] == '+') 
            Lnum++;
        else if (i > eql && str[i] == '-')
            Lnum++; 
    }
    return sum;
}

int dfs(int k, int pos, int cur) {
    if (k == Lnum) {
        if (cur == ans)  
            return true;
        return false;
    }
    if (Lnum - k > cnt1 - pos)
        return false;
    if (pos < cnt1 && cur + arr[pos] <= ans) {
        vis[pos] = 1; 
        if (dfs(k + 1, pos + 1, cur + arr[pos])) 
            return true;
        vis[pos] = 0;
    }
    if (pos < cnt1 && dfs(k, pos + 1, cur)) 
        return true;
    return false;
}

void outPut() {
    int x = 0, y = 0;
    for (int i = 0; i < cnt1; i++) {
        if (vis[i]) 
            front[x++] = arr[i];
        else
            back[y++] = arr[i]; 
    }

    printf("%d", front[--x]);
    for (int i = 0; i < L; i++) {
        printf(" %c ", Lsy[i]); 
        if (Lsy[i] == '+')
            printf("%d", front[--x]);
        if (Lsy[i] == '-')
            printf("%d", back[--y]); 
    }
    printf(" = ");
    printf("%d", back[--y]); 
    for (int i = 0; i < R; i++) {
        printf(" %c ", Rsy[i]); 
        if (Rsy[i] == '+')
            printf("%d", back[--y]);  
        if (Rsy[i] == '-')
            printf("%d", front[--x]);
    }
    printf("\n");
}

int main() {
    while (gets(str)) {
        int s = init(); 
        if (s % 2)
            printf("no solution\n");
        else {
            ans = s / 2;
            memset(vis, 0, sizeof(vis));
            if (dfs(0, 0, 0))
                outPut();  
            else 
                printf("no solution\n");
        }
    }    
    return 0;
}


评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值