--- tags: uva --- # Uva11832 - Account Book ## 題目大意 帳本上有許多條目,但條目上區別是收入還是支出的部分被塗掉了,所以我們需要找出可以確定哪幾條是收入還是支出並輸出出來(會給予最後的餘額) ## 重點觀念 - 應該算 dp + 二進制? - 參考 https://github.com/morris821028/UVa/blob/master/volume118/11832%20-%20Account%20Book2.cpp ## 分析 - 目標就是將所有加減的可能記錄起來,以 plus[i][j] 來看 i 只是用來區分此輪與下一輪, j 則是代表加到 j 這個數時所有有可能是收入的條目(二進位表示 1 則為有可能 0 為不可能) ## 程式題目碼 ```cpp= #include <string.h> #include <iostream> using namespace std; int main() { int n, f; while (cin >> n >> f, n != 0) { int a[n], roll = 0; for (int i = 0; i < n; i++) { cin >> a[i]; } long long plus[2][80005]; long long minus[2][80005]; memset(plus, 0, sizeof(plus)); memset(minus, 0, sizeof(minus)); plus[roll][40000 + a[0]] = 1; minus[roll][40000 - a[0]] = 1; int L = -a[0] + 40000; int R = a[0] + 40000; for (int i = 1; i < n; i++) { memset(plus[1 - roll], 0, sizeof(plus[0])); memset(minus[1 - roll], 0, sizeof(minus[0])); for (int j = L; j <= R; j++) { if (plus[roll][j] || minus[roll][j]) { int k = j + a[i]; plus[1 - roll][k] |= plus[roll][j] | (1LL << i); minus[1 - roll][k] |= minus[roll][j]; k = j - a[i]; plus[1 - roll][k] |= plus[roll][j]; minus[1 - roll][k] |= minus[roll][j] | (1LL << i); } } L -= a[i]; R += a[i]; roll = 1 - roll; } long long ans_p = plus[roll][f + 40000]; long long ans_m = minus[roll][f + 40000]; if (ans_p == 0 && ans_m == 0) { cout << "*"; } else { for (int i = 0; i < n; i++) { if ((ans_p >> i) & 1) { if ((ans_m >> i) & 1) { cout << "?"; } else { cout << "+"; } } else { cout << "-"; } } } cout << endl; } return 0; } ```