HDU 1709 The Balance (母函數)

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;
}


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章