1. 程式人生 > >河南省第十屆ACM題解 D 年終獎金

河南省第十屆ACM題解 D 年終獎金

題目描述
*公司承接了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; }