1. 程式人生 > >【OJ2726】集合問題,堆

【OJ2726】集合問題,堆

2726:集合問題
檢視 提交 統計 提問
總時間限制: 5000ms 記憶體限制: 65536kB
描述
有一組正整數,總數不超過1000,其中最大值記為M。現要將它們劃分成N個集合,使得每個集合的元素之和與M的差的絕對值的和最小。

集合A中當前各元素之和記為SUM(A),稱為A的負荷;SUM(A)與M之差的絕對值稱為A的負荷與理想負荷的偏差,簡稱為A的偏差。把這些整數劃分成N個集合的方法是:按照從大到小的順序,依次為每個整數分別選擇一個集合;確定一個整數所屬集合時,先計算各集合的負荷,將該整數分配給負荷最小的那個集合。

求使得各集合的偏差之和最小的劃分方案中,集合的數目N。如果這樣的方案不止一種,則輸出各方案中,集合數最大的那種方案的集合數N。
輸入
共輸入K+1個整數。其中第一個整數是K代表要劃分的整數總數,後面依次是K個整數的值。K不超過1000。
輸出
一個整數,代表集合數N。
樣例輸入
8
2 4 9
12 16
80 28
72
樣例輸出
3
寫在前面:人要是一急,控制變數名都會打錯
——————————————————————————————————————————————
思路:集合數量直接1-n暴力列舉,最後算一下最小和可過
程式碼:

#include<cstdio>
#include<algorithm>
#include<queue>
#include<cmath>
using namespace std;
int n,a[1010],minn=0X7fffffff,ans=0;
bool flag;
priority_queue <int,vector<int>,greater<int> > q;
inline int comp(int x,int y)
{
    return x>y;
}
main()
{
    scanf("%d"
,&n); for (int i=1;i<=n;i++) scanf("%d",&a[i]); sort(a+1,a+n+1,comp); for (int i=1;i<=n;i++) { int total=0; for (int j=1;j<=i;j++) q.push(0); for (int j=1;j<=n;j++) { int k=q.top(); q.pop(); q.push(k+a[j]); } for
(int j=1;j<=i;j++) total+=abs(a[1]-q.top()),q.pop(); if (minn>=total) ans=i,minn=total; else if (!flag) flag=1; else break;//一步小優化,不加也能過,加了能快一些,自己感受一下 } printf("%d",ans); }