UVa 10317 Equating Equations 解题报告(暴力)

Problem F

Equating Equations

Input: standardinput

Output: standardoutput

Time Limit: 6 seconds

Memory Limit: 32MB

 

Read equations with up to 16 terms and + and operators (not unary) and reorder theterms (but not the operators) so that the equations hold. For example

 
   1 + 2 = 4 - 5 + 6

isnot a correct equation but the terms can be rearranged thus so it is:

 
   6 + 2 = 4 - 1 + 5

Input

Standardinput consists of several pseudo-equations, one per line. Each pseudo-equationhas up to 16 integer terms and eachterm is less than 100. Adjacentterms are separated by one operator, and spaces always appear surrounding theterms. There is exactly one = operator in the equation

Output

Youroutput will consist of one line per input line, with the same operators and thesame terms. The order of the operators must be preserved, but the terms can bereordered so the equation holds. Any ordering such that the equation holds iscorrect. If there is more than one ordering any one of the orderings will do.If no ordering exists, a line containing

   no solution

should beprinted. One space should appear on either side of each operator and thereshould be no other spaces.

Sample Input

1 + 2 = 4 - 5 + 6
1 + 5 = 6 + 7

Sample Output

6 + 2 = 4 - 1 + 5
no solution
 
    解题报告:做起来很繁琐的一题。输入部分就很难处理,直接读整行,然后读int和char。
    正题部分,调换顺序使等式成立。等式左边的正号的数和等式右边的减号的数其实是加在一起的。简单来说就是把16个数分成两堆,使两堆相等即可。
    使用状态压缩(或者dfs什么的)枚举可能选择的数,如果刚好是所有数和的一半,那么等式成立,将数字填入相应的位置。代码如下:
#include <iostream>
#include <cstdio>
#include <algorithm>
#include <cstring>
#include <cmath>
#include <queue>
#include <vector>
#include <map>
#include <set>
#include <string>
#include <iomanip>
using namespace std;

#define ff(i, n) for(int i=0;i<(n);i++)
#define fff(i, n, m) for(int i=(n);i<=(m);i++)
#define dff(i, n, m) for(int i=(n);i>=(m);i--)
typedef long long LL;
typedef unsigned long long ULL;
void work();

int main()
{
#ifdef ACM
    freopen("in.txt", "r", stdin);
#endif // ACM

    work();
}

/***************************************************/

char str[222];
int pos = 0;
char ch;

int num[1111111];

int readInt()
{
    while(str[pos] == ' ') pos++;

    int ret = 0;
    while(isdigit(str[pos]))
        ret = ret * 10 + (str[pos++]-'0');
    return ret;
}

char readChar()
{
    while(str[pos] == ' ') pos++;
    return str[pos++];
}

void work()
{
    while(gets(str) && str[0])
    {
        vector<int> vint;
        vector<char> vch;

        pos = 0;
        while(vint.push_back(readInt()), vch.push_back(ch = readChar()), ch);

        int n = vint.size();
        int sum = 0;
        ff(i, n) sum += vint[i];
        if(sum&1)
        {
            puts("no solution");
            continue;
        }

        ch = '+';
        vector<int> vp;
        vector<int> vpp;
        vp.push_back(0);
        ff(i, n) if(vch[i] == ch)
        {
            vp.push_back(i+1);
        }
        else
        {
            if(vch[i] == '=')
                ch = '-';
            vpp.push_back(i+1);
        }

        int st = -1;
        int k = min(vp.size(), n - vp.size());
        ff(s, 1<<n)
        {
            int tmp = 0;
            int t = 0;
            ff(j, n) if(s&(1<<j))
                t++, tmp += vint[j];
            if(t == k && tmp == sum/2)
            {
                st = s;
                break;
            }
        }

        if(st == -1)
        {
            puts("no solution");
            continue;
        }

        if(k != vp.size()) st = ~st;

        vector<int> ans;
        ff(i, n) ans.push_back(-1);
        int sta = 0;
        ff(i, n) if(st & (1<<i))
            ans[vp[sta++]] = vint[i];

        sta = 0, st = ~st;
        ff(i, n) if(st & (1<<i))
            ans[vpp[sta++]] = vint[i];

        printf("%d", ans[0]);
        fff(i, 1, n - 1)
            printf(" %c %d", vch[i-1], ans[i]);
        puts("");
    }
}


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值