G - 阿汤的数组
Peace
題目描述
阿湯同學為了準備下學期的 ACM-ICPC,刷了很多的題目,他覺得自己已經比較厲害了,于是想出個題目考考你。現在他給你一個數組 A,問你是否能將該數組劃分成數組 B、C 使得 B 數組的平均數和C 數組的平均數相等,數組 B 和 C 都不能為空。
輸入描述:
從標準輸入讀入數據。
輸入包含多組數據,第一行一個整數 T 代表數據組數。接下來依次描述每組數據,對于每組數據:
第一行輸入正整數 N,第二行輸入 N 個非負整數
1≤|A|≤30 (數組 A 的長度范圍在 1 到 30 之間 )
0≤A[i]≤10000 (數組 A 中的元素)
輸出描述:
輸出到標準輸出。
對于每組數據,輸出一行:
如果能劃分成滿足題目要求的數組 B 和 C 則輸出 yes,否則輸出no
輸入
1
8
1 2 3 4 5 6 7 8
輸出
yes
說明
樣例說明:將數組 A 劃分成【1,4,5,8】和【2,3,6,7】,平均數為 4.5
思路
DP:dp[ K ] [ Z ] : Z 表示已經選了幾個數, K表示當前數組的和。如果K / Z == Average 就是yes,否則no。
即可得到數組B 和數組A的平均數相等,所以我們可以對數組A中的元素減 去數組A的平均值,問題轉化為在數組A中找到一個數組B使得數組B的和為0.顯 然的做法是枚舉A中數字的所有可能的組合,但是因為A的長度多達30, 230會超 時,所以考慮拆分成兩個部分,每一邊最多15個元素,復雜度變成 215,然后二 分在兩邊找答案就可以了。
AC
#include<bits/stdc++.h> #define N 300005 #define mem(a, b) memset(a, b, sizeof(a)) #define ll long long using namespace std; const double eps = 1e-6; bool dp[N][31]; int a[31], n, MAX; double ave; int solve () { // if (n == 1) return 0; // i 即將放入背包的元素 for (int i = 1; i <= n; i++) { // j 已經放入背包的元素總和 for (int j = MAX; j >= 0; j--) { // k 已經放入背包的元素個數 // k < n - 1, 因為數組不為空,不能全部放入背包 for (int k = 0; k < n - 1; k++) { // 如果放入背包元素合法,就放入新的元素 if (dp[j][k]) {int temp = j + a[i];MAX = max(temp, MAX);dp[temp][k + 1] = 1;if (abs(temp * 1.0 / (k + 1) - ave) < eps) return 1;}}}}return 0; }int main() { // freopen("in.txt", "r", stdin);int t;scanf("%d", &t);while (t--) {ave = 0;scanf("%d", &n);for (int i = 1; i <= n; i++) {scanf("%d", &a[i]);ave += a[i];}ave /= n;mem(dp, 0);dp[0][0] = 1;MAX = 0;if (solve()) printf("yes\n");else printf("no\n"); }return 0; }總結
- 上一篇: F - 阿汤的疑惑(模拟取余+分解质因数
- 下一篇: 第十一届河南省赛--A计划日