TOJ 2898

来源:互联网 发布:北明软件 中标 编辑:程序博客网 时间:2024/05/16 10:22


题目标题:

Employment Planning


题目连接:

http://acm.tzc.edu.cn/acmhome/problemdetail.do?&method=showdetail&id=2898


题目类型:

动态规划 


数据结构:

// month, workerint dp[15][MAXPLE];


思路分析:

给定每个月最低工作人数,

决定雇佣或者裁员或者保持原样

使得总支出最小

典型的动态规划问题


关键是以每个月为一个决策节点

对当月的不同人数对比上个月的各种情况人数施以计算,

当月每个人数都保留最优有效解

则最后一个月的最少支出为答案..




比如 第一个月 对最少人数至最多人数计算 保留各个值

第二个月 最低人数9个人的情况 对 一月份各个人数情况计算 取最小值

再10个人的情况 对上一个月再执行重复的步骤 保留当月最小值


证明:

1. 所有雇员行为都是越迟越好, 至少不会得到更差的解

此思路建立在每个月都是对前几个月独立的情况上

每个月相当于都是新的决策点 不受过去情况的影响.


源代码:

#include <iostream>#include <stdio.h>using namespace std;#define MAXPLE 205// month, workerint dp[15][MAXPLE];int main(){int i, j, k, maxples;int months;int hiring, salary, firing;int arr[13];while( scanf( "%d", &months ), months ){maxples = -1;memset( arr, 0, sizeof( arr ) );memset( dp, 0, sizeof( dp ) );scanf( "%d%d%d", &hiring, &salary, &firing );for( i = 1; i <= months; i ++ ){scanf( "%d", arr + i );if( arr[i] > maxples ){maxples = arr[i];}}for( i = arr[1]; i <= maxples; i ++ ){dp[1][i] = hiring * i + salary * i;}for( i = 2; i <= months; i ++ ){for( j = arr[i]; j <= maxples; j ++ ){int tmp = 0, min = INT_MAX;for( k = arr[i - 1]; k <= maxples; k ++ ){if( dp[i - 1][k] ){tmp = dp[i - 1][k] + j * salary + ( j > k ? ( j - k ) * hiring : ( k - j ) * firing );if( tmp < min ){min = tmp;}}}dp[i][j] = min;}}int m = INT_MAX;for( i = arr[months]; i <= maxples; i ++ ){if( dp[months][i] < m ){m = dp[months][i];}}printf( "%d\n", m );}return 0;}


优化:

只需对所有月份中最大人数的那个当上界即可

没有必要对所有可能的人数求解

在 HDOJ 15MS 在 TOJ 500MS 左右 

0 0
原创粉丝点击