动态规划 Elevators in Jiayuan Students' Apartment hdu 3576

题目连接:http://acm.hdu.edu.cn/showproblem.php?pid=3576

题目大意:某建筑物内有三个电梯,每个电梯最多可承受c人,此建筑物最高位16层,一层的不用乘坐电梯,现在有m人,问怎么样分配这m个人使得三个电梯上升过程中停止的次数最少,要求这m个人必须一次运上去而不能让电梯回来运。

题目思路:这个题就是枚举每一层上的人分配的所有可能然后选择最小停次数就可以。

dp[f][i][j][k]表示到第f层三个电梯人数分别是i、j、k时的最小停次数,用一个hash记录每层需要停的人数

代码:

#include <iostream> #include <cstdio> #include <cstring> using namespace std; const int maxn=99999999; int dp[18][18][18][18]; int hash[18]; int n,c,m; int min(int a,int b) { return a<b?a:b; } int DP() { memset(dp,-1,sizeof(dp)); dp[1][0][0][0]=0;//第一层没人下 for (int f=2;f<=16;++f)//枚举所有有效层数 { for (int i=0;i<=c;++i) { for (int j=0;j<=c;++j) { for (int k=0;k<=c;++k) { if (dp[f-1][i][j][k]==-1)continue;//第f-1层时i、j、k没处理,只有处理了才回向上扩展第f层 if (i+j+k>m)continue; int res=0; for (int x=0;x<=hash[f];++x)//这里往下是枚举将第f层的人分配到三个电梯中的方案 { for (int y=0;y<=hash[f];++y) { if (x+y>hash[f])continue; int z=hash[f]-x-y; if (i+x>c || j+y>c || k+z>c)continue; res=dp[f-1][i][j][k]+(x>0)+(y>0)+(z>0);//只要x、y、z不为0则需要在这层停一次 if (dp[f][i+x][j+y][z+k]==-1 || dp[f][i+x][j+y][z+k]>res) { dp[f][i+x][j+y][z+k]=res; } } } } } } } int ans=maxn; for (int i=0;i<=c;i++)//枚举进行选择最少停次数 { for (int j=0;j<=c;j++) { if (i+j>m)continue; int k=m-i-j; if (dp[16][i][j][k]==-1)continue; ans=min(ans,dp[16][i][j][k]); } } return ans; } int main() { int t; scanf("%d",&t); for (int cas=1;cas<=t;++cas) { printf("Case %d: ",cas); scanf("%d%d",&c,&m); int a; memset(hash,0,sizeof(hash)); for (int i=1;i<=m;i++) { scanf("%d",&a); hash[a]++; } int ans=DP(); printf("%d\n",ans); } }


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值