E Elevators in Jiayuan Students' Apartment

E  Elevators in Jiayuan Students' Apartment

 Description

There are three elevators in the Building Bof Jiayuan Students' Apartment in BJTU, which carry a lot of students to go upand down every day.

There're 16 floors in the Building B. Thestudents living on the 1F don't need to wait for the elevators, so all the mstudents want to get to the 2F or higher.

Supposed that the capacity of each elevatoris C( 1 ≤ C ≤ 13 ). Now there are m( 1 ≤ m ≤ 3*C ) students waitingfor upstairs on the first floor, while all the three elevators stop on thefirst floor. You can arrange the way how they go upstairs, that Nobody willleft on the first floor when the elevators are in the process of rising. Howmany times do the three elevators have to stop at least to carry all the mstudents to the right floor?

Input

The first line of input contains a numbert, which means there are t cases of the test data.

In each case of testing data, the firstline contains two integers C and m.

In the next line, there are m integers f (2 ≤ f ≤ 16 ), indicate the floor a student wants to reach.

Output

For each case of testing data, the firstline is written as "Case n: X", where n is the case number, X is theminimum times the elevators have to stop in the process of rising.

Sample Input

2

1 3

2 4 16

2 6

9 9 9 6 6 6

Sample Output

Case 1: 3

Case 2: 4

时隔半年之久,第一次写了道DP问题。想了许久,一直以为是搜索,脑海中根本压根就没DP的影子!

参考了标程后感慨——这真是一道相当经典的题目啊!可惜自己没能写出来,感觉真的很遗憾!

dp[f][x+u][y+v][z+data[f]-u-v] 

= min{dp[f-1][x][y][z]+(u!=0)+(v!=0)+((data[f]-u-v)!=0), dp[f][x+u][y+v][z+data[f]-u-v]} 

其中dp[f][x][y][z]表示到达楼层f,三人电梯人数分别为x、y、z时的最优解!

data[f]表示去楼层f的人数!

DP问题嘛,给你状态存储数组,给个状态转移方程。够了!

hehe...

#include<iostream>
#include<cstdio>
using namespace std;

int dp[20][20][20][20];

int main()
{
    int i,j,k;
    int cases;
    scanf("%d", &cases);
    int t = 1;
    while(t <= cases)
    {
            int c,m;
            scanf("%d %d", &c, &m);
            int layer[20];
            memset(layer, 0, sizeof(layer));
            for(i=0; i<m; i++)
            {
                     cin>>k;
                     layer[k] ++;
            }
                     
                     memset(dp, -1, sizeof(dp));
                     int f,x,y,z,u,v;
                     dp[1][0][0][0] = 0;
                     for(f=2; f<=16; f++)
                     for(x=0; x<=c; x++)
                     for(y=0; y<=c; y++)
                     for(z=0; z<=c; z++)
                     {
                              if(dp[f-1][x][y][z] == -1) continue;
                              for(u=0; u<=layer[f]; u++)
                              for(v=0; v<=layer[f]; v++)
                              {
                                  if(u+v>layer[f]) continue;
                                  if(x+u>c||y+v>c||z+layer[f]-u-v>c) continue;
                                  int tmp = 0;
                                  tmp = dp[f-1][x][y][z]+(u!=0)+(v!=0)+((layer[f]-u-v)!=0);
                                  if(dp[f][x+u][y+v][z+layer[f]-u-v] == -1 || dp[f][x+u][y+v][z+layer[f]-u-v] > tmp)
                                  dp[f][x+u][y+v][z+layer[f]-u-v] = tmp; 
                                   }                             
                              }
                              
                              int res = 10000000;
                              for(i=0; i<=c; i++)
                              for(j=0; j<=c; j++)
                              if(i+j <=c && dp[16][i][j][m-i-j] < res && dp[16][i][j][m-i-j] != -1)
                              res = dp[16][i][j][m-i-j];
                              cout<<"Case "<<t<<": "<<res<<endl;
                    
            }
            return 0;
    }


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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值