uva 10317 - Equating Equations
题目链接:
1. 先对等式进行移项,假设原来为1 + 2 = 4 - 5 + 6,那么移动之后就变为了 1 + 2 - 4 + 5 + 6 = 0. 并计算出所有数字之和sum,和等式左边中的正数个数plusNum
2. 然后就演变成了“从n个数中选取总和为sum/2的plusNum个数字组成正数部分”,因为如果等式成立,那么所有正数之和与所有负数之和的绝对值一定是相等的。正样的话,对于每个数,要么取,要么不取,复杂度就变为了 2^16
3. 减枝: 1) 每次递归时,如果当前值加上要选的那个数之和大于sum/2,则不选
2) 如果所有数字之和为奇数,那么直接no solution。这个优化相当大,直接从1.9s降到了0.08s。不过rank第一的神牛的0.02s真不知道怎么跑出来的 Orz..
#include<cstdio>
#include<cstring>
const int maxn = 1000;
char str[10000];
char sigma[maxn];
bool vis[maxn];
int num[maxn], ans[maxn], n, idx;
int plus[maxn], leftNum, plusNum, sum;
inline void read(){
idx = 1;
sscanf(str, "%d", &num[0]);
sum = num[0];
int len = strlen(str);
for(int i=1; i<len; ++i){
if(str[i]=='+' || str[i]=='-' || str[i]=='=') {
if(str[i] == '=')
leftNum = idx;
sigma[idx] = str[i];
sscanf(str+i+1, "%d", &num[idx]);
sum += num[idx++];
}
}
// 把等式全部移到左边后,计算有多少个加号
plusNum = 1;
for(int i=1; i<idx; ++i){
if(i<leftNum && sigma[i] == '+'){
++plusNum;
} else if(i>leftNum && sigma[i] == '-')
++plusNum;
}
}
bool dfs(int cur, int pos, int tot){
if(plusNum-cur > idx-pos)
return false;
if(cur == plusNum){
if(tot*2 == sum) return true;
return false;
}
if(pos<idx && (tot+num[pos])*2 <= sum){
vis[pos] = true;
plus[cur] = num[pos];
if(dfs(cur+1, pos+1, tot+num[pos]))
return true;
}
vis[pos] = false;
if(pos<idx && dfs(cur, pos+1, tot))
return true;
return false;
}
inline void solve(){
//注意减枝!如果sum为奇数那么直接输出no solution
memset(vis, 0, sizeof(vis));
if((sum&1)==0 && dfs(0, 0, 0)){
int id=1;
ans[0] = plus[0];
for(int i=1; i<idx; ++i){
if(i<leftNum && sigma[i]=='+') {
ans[i] = plus[id++];
} else if(i>leftNum && sigma[i]=='-'){
ans[i] = plus[id++];
}
}
int k=1;
for(int i=0; i<idx; ++i)if(!vis[i]){
while(k<leftNum && sigma[k]=='+' && k<idx) ++k;
while(k>leftNum && sigma[k]=='-' && k<idx) ++k;
ans[k++] = num[i];
}
printf("%d", ans[0]);
for(int i=1; i<idx; ++i)
if(i==leftNum) printf(" = %d",ans[i]);
else printf(" %c %d", sigma[i], ans[i]);
puts("");
}else{
puts("no solution");
}
}
int main(){
while(gets(str)){
read();
solve();
}
return 0;
}

浙公网安备 33010602011771号