Dormitory's Elevator | ||
Accepted : 70 | | Submit : 394 |
Time Limit : 1000 MS | | Memory Limit : 65536 KB |
Problem DescriptionThe new dormitory has N(1≤N≤100000) floors and M(1≤M≤100000)students. In the new dormitory, in order to save student's time as well as encourage student exercise, the elevator in dormitory will not stop in adjacent floor. So if there are people want to get off the elevator in adjacent floor, one of them must walk one stair instead. Suppose a people go down 1 floor costs A energy, go up 1 floor costs B energy(1≤A,B≤100). Please arrange where the elevator stop to minimize the total cost of student's walking cost.All students and elevator are at floor 1 initially, and the elevator can not godown and can stop at floor 2. InputFirst line contain an integer T, there are T(1≤T≤10) cases. For each case T, there are two lines. First line: The number of floors N(1≤N≤100000), and the number of students M(1≤M≤100000),A,B(1≤A,B≤100) Second line: M integers (2≤A[i]≤N), the student's desire floor. OutputOutput case number first, then the answer, the minimum of the total cost of student's walking cost. Sample Input13 2 1 12 3 Sample OutputCase 1: 1 |
解题思路:这个题最开始想开二维dp[i][j],一看数据就pass了。然后想了下,dp[i]表示电梯停到第i层楼时,学生到1-i层楼的最小化费。这样为了保证最小花费,肯定要尽可能多的使用电梯,那么dp[i]的状态首先肯定是可以从dp[i-2]转移过来的,如果仅仅只有dp[i-2],那么电梯就可能会停到2-4-6.....,中间停奇数层的可能就被忽略了。所以会有dp[i-3]的情况,保证了奇偶层都可能停,dp[i-4]就没有必要了,因为肯定会坐电梯上来的。这样在第i层,i-1层,i-2层之间进行状态转移。详见代码。
#include<iostream>
#include<cstdio>
#include<cstring>
using namespace std;
const int maxn = 100005;
int n,m,A,B,dp[maxn],F[maxn],cnt[maxn];
int MIN(int a,int b,int c,int d)
{
if(a <= b && a <= c && a <= d) return a;
if(b <= a && b <= c && b <= d) return b;
if(c <= a && c <= b && c <= d) return c;
if(d <= a && d <= b && d <= c) return d;
}
int main()
{
int t,cas = 1;
scanf("%d",&t);
while(t--)
{
scanf("%d%d%d%d",&n,&m,&A,&B);
memset(cnt,0,sizeof(cnt));
memset(dp,0,sizeof(dp));
for(int i = 1; i <= m; i++)
{
scanf("%d",&F[i]);
cnt[F[i]]++;
}
dp[1] = dp[2] = 0;
dp[3] = min(A,B)*cnt[2];
for(int i = 4; i <= n; i++)
{
dp[i] = dp[i-2] + min(A,B)*cnt[i-1];
int tmp1 = cnt[i-1]*A + cnt[i-2]*2*A; //从i楼下到i-1和i-2楼
int tmp2 = cnt[i-1]*2*B + cnt[i-2]*B; //从i-3楼上到i-1和i-2楼
int tmp3 = cnt[i-1]*A + cnt[i-2]*B; //i楼下到i-1楼,i-3楼上到i-2楼
int tmp4 = cnt[i-2]*2*A + cnt[i-1]*2*B; //i楼下到i-2楼,i-3楼上到i-1楼
dp[i] = min(dp[i],dp[i-3] + MIN(tmp1,tmp2,tmp3,tmp4));
}
int ans = dp[n];
ans = min(ans,dp[n-1]+cnt[n]*B);
ans = min(ans,dp[n-2]+cnt[n]*2*B + cnt[n-1]*B);
printf("Case %d: %d\n",cas++,ans);
}
return 0;
}