河南省第十屆ACM題解 D 年終獎金
阿新 • • 發佈:2019-02-18
題目描述
*公司承接了N個專案需要年底完成,每個專案有一定的難度係數。由於專案太多了,需要招聘大量的技術人員。要求每個技術人員至少完成K個專案。
考慮到有些專案之間相似性以及專案的難易程度,為了避免某些員工只挑選輕鬆專案,CEO提出了一個獎勵機制,當技術人員完成分配給他的任務後,年終可以得到一筆獎金,其得到的酬金將是C + (Tmax–Tmin)2。其中,Tmax表示所做專案的最大的難度係數,Tmin是難度係數的最小值。
你能否計算一下,為了完成所有專案,*公司年終至少需要支付多少酬金?
輸入
輸入有多組測試資料。對每組測試資料:
第一行: N K C (1<=N,K<=100 1<=C<=5000 ) 第二行 N個正整數分別描述N個專案的難度係數。(1<=難度係數<=10000)
輸出
對每組測試資料:輸出佔一行,一個整數。即,*公司年終至少需要支付的酬金數。
樣例輸入
2 1 1
2 4
10 2 3
1 4 10 3 10 1 8 3 8 3
樣例輸出
2
13
提示
第一組測試資料,如果一個人完成,酬金為1 + (4–2)2 = 5;如果分給兩個人去完成,收費為1 + 1 = 2。
解題思路:這是一個區間dp問題,首先對專案的難度係數進行一個從小到大的排序,因為題目要求出最少年終獎金,所以要先將dp刷成 INF,dp[0]=0,然後寫出狀態轉移方程dp[i]=min(dp[j]+c+(a[i]-a[j+1])*(a[i]-a[j+1]),dp[i]);
#include<stdio.h>
#include <bits/stdc++.h>
#define MAX 0x3f3f3f3f
#define min(x,y)(x<y?x:y)
using namespace std;
int a[110];
int dp[110];
int main()
{
int n,k,c;
while(~scanf("%d%d%d",&n,&k,&c))
{
memset(dp,MAX,sizeof(dp));
for(int i=1;i<=n;i++)
scanf ("%d",&a[i]);
sort(a+1,a+1+n);
if(n<k){//這裡需要注意一下的是如果任務不足K個,直接用最大減最小的平方
printf("%d\n",(a[n]-a[1])*(a[n]-a[1]));
continue;
}
dp[0]=0;
for(int i=k;i<=n;i++)
{
for(int j=0;j<=i-k;j++)
{
if(j<k&&j!=0)
continue;
dp[i]=min(dp[j]+c+(a[i]-a[j+1])*(a[i]-a[j+1]),dp[i]);
}
}
printf("%d\n",dp[n]);
}
return 0;
}