poj 3459(背包问题)

来源:互联网 发布:王者荣耀kda算法 编辑:程序博客网 时间:2024/06/10 19:43

题意:题目大意是说n个人做m项工程,然后给出工人的薪水,和工程按期完工的概率,以及按时完工的酬劳和未按时完工的罚款,要求出最大利润。。需要注意的 是,薪水输出的是欧元为单位,输出的是以分为单位。


解题思路:简单的背包问题,dp[i][j]表示前i个工程,分配j个人完成的最大期望利润。dp[i][j] = max{dp[i-1][k] + cost}, 0 <= k <= j

这道题的利润可能为负,所以初始化不能直接赋0,这里WA了一次。总体不是很难,看懂题意就比较简单了。


#include<iostream>#include<cstdio>#include<cstring>#define max(a,b) a > b ? a : bconst int maxn = 105;const int inf = 0x7fffffff;int n,m,salary,p[maxn][maxn];int reward[maxn],punish[maxn];int dp[maxn][maxn]; //dp[i][j]表示前i个项目共j人做得到的最大利润int main(){int t;scanf("%d",&t);while(t--){scanf("%d%d%d",&m,&n,&salary);//m个项目,n个人for(int i = 1; i <= m; i++){for(int j = 1; j <= n; j++)scanf("%d",&p[i][j]);scanf("%d%d",&reward[i],&punish[i]);}for(int i = 0; i <= m; i++)for(int j = 0; j <= n; j++) dp[i][j] = -inf;for(int i = 0; i <= n; i++)dp[1][i] = p[1][i] * (reward[1] - i * salary) - (100 - p[1][i]) * punish[1]; for(int i = 2; i <= m; i++)for(int j = 0; j <= n; j++)for(int k = 0; k <= j; k++){dp[i][j] = max(dp[i][j],dp[i-1][j-k] + p[i][k] * (reward[i] - k * salary) - (100 - p[i][k]) * punish[i]);}int ans = -inf;for(int i = 0; i <= n; i++)ans = max(ans,dp[m][i]);printf("%d\n",ans);for(int i = 0; i <= n; i++)if(ans == dp[m][i])printf("%d ",i);printf("\n");}return 0;}


0 0
原创粉丝点击