E Elevators in Jiayuan Students' Apartment

来源:互联网 发布:网络安全法意义 编辑:程序博客网 时间:2024/05/08 10:49

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;    }