NYOJ-1070-诡异的电梯[Ⅰ]

描述
新的宿舍楼有 N(1≤N≤100000) 层 and M(1≤M≤100000)个学生. 在新的宿舍楼里, 为了节约学生的时间也为了鼓励学生锻炼身体, 所以规定该宿舍楼里的电梯在相邻的两层之间是不会连续停下(即,如果在第2层停下就不能在第3层停下。).所以,如果有学生在相邻的两层之间要停下, 则其中的一部分学生必须选择走楼梯来代替。规定:一个人走下一层楼梯的花费为A,走上一层楼梯的花费为B。(1≤A,B≤100)现在请你设计一个算法来计算出所有学生走楼梯花费的最小费用总和。 所有的学生一开始都在第一层,电梯不能往下走,在第二层的时候电梯可以停止。

输入
输入有几组数据T。T(1≤T≤10)
每组数据有N (1≤N≤100000),M(1≤M≤100000),A,B(1≤A,B≤100)。
接下来有M个数字表示每个学生想要停的楼层。

输出
输出看样例。
样例输入
1
3 2 1 1
2 3
样例输出
Case 1: 1

一个简单的一维dp,为了得到最短时间费用,需要考虑到隔一层下与隔两层下的情况,其中隔两层下的情况又分为四种,具体代码如下,注释很清楚,应该很容易理解的!

#include <stdio.h>
#include <string.h>
#define MAXSIZE 100005
#define MIN(a, b) a < b ? a : b

int main(int argc, const char * argv[])
{
    int T;
    int N, M, A, B;
    int to;
    int wantTo[MAXSIZE];
    int i, key = 0;
    int cost[MAXSIZE];

    scanf("%d", &T);
    while (T--)
    {
        key++;
        memset(wantTo, 0, sizeof(wantTo));
        memset(cost, 0x3F, sizeof(cost));

        scanf("%d %d %d %d", &N, &M, &A, &B);
        for (i = 0; i < M; i++)
        {
            scanf("%d", &to);
            wantTo[to]++;
        }

        int temp;
        int min = MIN(A, B);
        cost[0] = cost[1] = cost[2] = 0;
        for (i = 3; i <= N; i++)
        {
            cost[i] = MIN(cost[i], cost[i - 2] + wantTo[i - 1] * min);
            /*

             + i层
             + ⬆️
             + (i - 1)层
             + ⬇️
             + (i - 2)层

             */

            if (i - 3 > 0)
            {
                temp = MIN(wantTo[i - 1] * A + wantTo[i - 2] * 2 * A, wantTo[i - 1] * 2 * B + wantTo[i - 2] * B);
                /*

                 + i层
                 + ⬆️   /
                 + (i - 1)层
                 + ⬆️⬆️ / ⬇️⬇️
                 + (i - 2)层
                 +      / ⬇️
                 + (i - 3)层

                 */

                temp = MIN(temp, wantTo[i - 1] * A + wantTo[i - 2] * B);
                /*

                 + i层
                 + ⬆️
                 + (i - 1)层
                 + (i - 2)层
                 + ⬇️
                 + (i - 3)层

                 */

                temp = MIN(temp, wantTo[i -1] * 2 * B + wantTo[i - 2] * 2 * A);
                /*

                 + i层
                 + (i - 1)层
                 + ⬇️⬇️⬆️⬆️
                 + (i - 2)层
                 + (i - 3)层

                 */

                cost[i] = MIN(cost[i], cost[i - 3] + temp);
            }
        }

        printf("Case %d: %d\n", key, cost[N]);
    }

    return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值