Question link:
Http://uva.onlinejudge.org/index.php? Option = com_onlinejudge & Itemid = 8 & category = 457 & page = show_problem & problem = 1258
1. perform the shift in a peering manner. If the original value is 1 + 2 = 4-5 + 6, then the move is changed to 1 + 2-4 + 5 + 6 = 0. calculate the sum of all numbers and the positive number on the left of the equation plusnum.
2. then it evolved into "selecting plusnum numbers sum/2 from N numbers to form a positive part", because if the equation is true, then the absolute values of the sum of all positive numbers and all negative numbers must be equal. If it is positive, the complexity will change to 2 ^ 16 for each number, either or not.
3. subtraction: 1) during each recursion, if the sum of the current value plus the number to be selected is greater than sum/2
2) If the sum of all numbers is an odd number, there is no solution directly. This optimization is quite large, with a direct reduction from 1.9s to 0.08 s. However, Rank's first goon's 0.02s really don't know how to run 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 (St R + I + 1, "% d", & num [idx]); sum + = num [idx ++] ;}// after moving all equations to the left, calculate the number of plus signs (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 () {// pay attention to reducing branches! If sum is an odd number, no solution memset (VIS, 0, sizeof (VIS) is directly output; 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 ;}