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

题解

只考虑当前的状态i,设dp[i]为到第i层的最少费用

若电梯在第i-1层停下,则需要从第i-1层走到第i层

若电梯在第i-1层未停下,则到达第i-1层有两种方式(从第i层下来或者从第i-2层上去)

所以可以得出如下递推式:

int temp1= dp[i-1]+b*v[i];
int temp2=min(a,b)*v[i-1]+dp[i-2];
dp[i]=min(temp1,temp2);

注意:

从前往后考虑,第i层的代价不会受到第i层以上的的层数影响,只会受到第i层以下的层数影响。因为循环到i+1时,会考虑第i层是从上下来还是从下上去(同以第i层为yan’研究对象的解题思路是一样的)。

代码

#include<stdio.h>
#include<string.h>
#include<algorithm>
using namespace std;
int dp[100001];
int v[100001];
int main(){
    int n,m,t,a,b;
    scanf("%d",&t);
    int Case=1;
    while(t--){
        scanf("%d%d%d%d",&n,&m,&a,&b);
        memset(v,0,sizeof(v));
        memset(dp,0,sizeof(dp));
        for(int i=1;i<=m;i++){
            int temp;
            scanf("%d",&temp);
            v[temp]++;
        }
        dp[1]=dp[2]=0;
        for(int i=3;i<=n;i++){
            int temp1= dp[i-1]+b*v[i];
            int temp2=min(a,b)*v[i-1]+dp[i-2];
            dp[i]=min(temp1,temp2);
        }
        printf("Case %d: ",Case++);
        printf("%d\n",dp[n]);
    }
    return 0;
}


猜你喜欢

转载自blog.csdn.net/qq_27690765/article/details/89356711
今日推荐