The Balance
Time Limit: 1000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others)Total Submission(s): 5388 Accepted Submission(s): 2173
Problem Description
Now you are asked to measure a dose of medicine with a balance and a number of weights. Certainly it is not always achievable. So you should find out the qualities which cannot be measured from the range [1,S]. S is the total quality of all the weights.
Input
The input consists of multiple test cases, and each case begins with a single positive integer N (1<=N<=100) on a line by itself indicating the number of weights you have. Followed by N integers Ai (1<=i<=N), indicating the quality of each weight where 1<=Ai<=100.
Output
For each input set, you should first print a line specifying the number of qualities which cannot be measured. Then print another line which consists all the irrealizable qualities if the number is not zero.
Sample Input
3
1 2 4
3
9 2 1
Sample Output
0
2
4 5
題意:給定一系列重量的砝碼,然後問由這些砝碼不能稱出的重量有多少,並且打印這些重量,重量範圍爲1-s其中s爲所有砝碼的質量總和。
值得注意的是這個題目中的砝碼可以在天平兩遍都放。所以母函數完了,要記得考慮一下兩遍放的情況。最後將這些不能稱取的重量輸出就可以了。我這裏的做法麻煩了,因爲只要求重量能否稱出,而不需要計算有多少種稱出方法,所以不用考慮砝碼重量重複的情況,即無需用hash的方法把重量處理。直接正常的讀入然後母函數就可以了,過幾天會修改下。
#include <cstdio>
#include <cstdlib>
#include <iostream>
#include <string>
#include <algorithm>
#include <cstring>
#include <vector>
using namespace std;
const int MAXX = 102;
int weights[MAXX],cnt[MAXX],pos;
int res[MAXX*MAXX], tmp[MAXX*MAXX], cc[MAXX*MAXX];
vector<int> pr;
int main(){
int n,s,weight,ans;
while (cin >> n){
s = 0;
pos = 0;
memset(cnt, 0, sizeof(cnt));
for (int i = 0; i < n; ++i){
cin >> weight;
s += weight;
if (cnt[weight] == 0){
weights[pos++] = weight;
}
++cnt[weight];
}
memset(res, 0, sizeof(res));
memset(tmp, 0, sizeof(tmp));
//母函數的經典代碼
for (int i = 0; i <= cnt[weights[0]]; ++i){
res[i*weights[0]] = 1;
}
for (int i = 1; i < pos; ++i){
for (int j = 0; j <= s; ++j){
for (int k = 0; k <= cnt[weights[i]] && k*weights[i] + j <= s; ++k){
tmp[k*weights[i] + j] += res[j];
}
}
for (int j = 0; j <= s; ++j){
res[j] = tmp[j];
tmp[j] = 0;
}
}
//計算差值及天平的兩遍都放砝碼時可稱出的重量
memset(cc, 0, sizeof(cc));
for (int i = 0; i <= s; ++i){
for (int j = i+1; j <= s; ++j){
if (res[i] != 0 && res[j] != 0){
cc[j - i] = 1;
}
}
}
ans = 0;
pr.clear();
for (int i = 0; i <= s; ++i){
if (res[i] == 0 && cc[i]==0){
++ans;
pr.push_back(i);
}
}
cout << ans << endl;
if (ans == 0)continue;
for (int i = 0; i < ans; ++i){
cout << pr[i];
if (i != ans - 1){
cout << " ";
}
}
cout << endl;
}
}
修改後的代碼
#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <vector>
using namespace std;
const int MAXX = 102;
int weights[MAXX];
bool tmp[MAXX*MAXX], ans[MAXX*MAXX], cc[MAXX*MAXX];
int cnt, s;
vector<int> ptf;
int main(){
int n;
while (cin >> n){
s = 0;
for (int i = 0; i < n; ++i){
cin >> weights[i];
s += weights[i];
}
memset(ans, 0, sizeof(ans));
memset(tmp, 0, sizeof(tmp));
for (int i = 0; i <= 1; ++i){
ans[i*weights[0]] = 1;
}
for (int i = 1; i < n; ++i){
for (int j = 0; j <= s; ++j){
for (int k = 0; k <= 1 && j + k*weights[i] <= s; ++k){
tmp[j + k*weights[i]] = (tmp[j + k*weights[i]] || ans[j]);
}
}
for (int j = 0; j <= s; ++j){
ans[j] = tmp[j];
tmp[j] = false;
}
}
memset(cc, 0, sizeof(cc));
for (int i = 0; i <= s; ++i){
for (int j = i + 1; j <= s; ++j){
if (ans[i] && ans[j]){
cc[j - i] = true;
}
}
}
cnt = 0;
ptf.clear();
for (int i = 0; i <= s; ++i){
if (!ans[i] && !cc[i]){
++cnt;
ptf.push_back(i);
}
}
cout << cnt << endl;
if (cnt == 0)continue;
for (int i = 0; i < cnt; ++i){
cout << ptf[i];
if (i != cnt - 1){
cout << " ";
}
}
cout << endl;
}
return 0;
}