NYOJ 诡异的电梯 && nyoj 1204 魔法少女
诡异的电梯【Ⅰ】
时间限制:1000 ms | 内存限制:65535 KB
难度:3
- 描述
-
新的宿舍楼有 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
题目讲解:题目的状态转移方程是比较难想,但是画一下图就能发现转移方程;
下面图解now代表当前的楼层:到达每一个楼层,共有下面四种情况;
AC代码: -
1 #include<iostream> 2 #include<algorithm> 3 #include<cstdio> 4 #include<cstring> 5 #include<queue> 6 #include<string> 7 #include<cmath> 8 using namespace std; 9 const int N = 1e5+10; 10 const int MAX=0x3fffffff; 11 int dp[N],ma[N]; 12 int main() 13 { 14 int T,m,n,down,up,cout=1; 15 scanf("%d",&T); 16 while(T--) 17 { 18 int x; 19 memset(ma,0,sizeof(ma)); 20 fill(dp,dp+N,MAX); 21 dp[0]=dp[1]=dp[2] = 0; 22 scanf("%d %d %d %d",&n,&m,&down,&up); 23 int ab = min(down,up); 24 for(int i = 1;i<=m; i++) 25 { 26 scanf("%d",&x); 27 ma[x]++; 28 } 29 for(int i = 3; i<=n; i++) 30 { 31 dp[i] =min( dp[i],dp[i-2]+ma[i-1]*ab); 32 if(i>=4) 33 { 34 int temp = MAX; 35 temp = min(ma[i-2]*up*2+ma[i-1]*up,ma[i-2]*down+ma[i-1]*down*2);//同上同下 36 temp = min(temp,ma[i-2]*down+ma[i-1]*up);//一下一上 37 temp = min(temp,ma[i-2]*2*up+ma[i-1]*down*2);//一上一下 38 dp[i]=min(dp[i],temp+dp[i-3]); 39 } 40 } 41 printf("Case %d: %d\n",cout++,dp[n]); 42 } 43 return 0; 44 }
1204:魔法少女:
- 描述
- 前些时间虚渊玄的巨献小圆着实火了一把。 在黑长直(小炎)往上爬楼去对抗魔女之夜时,她遇到了一个问题想请你帮忙。 因为魔女之夜是悬浮在半空的,所以她必须要爬楼,而那座废墟一共有n层,而且每层高度不同,这造成小炎爬每层的时间也不同。不过当然,小炎会时间魔法,可 以瞬间飞过一层或者两层[即不耗时]。但每次瞬移的时候她都必须要至少往上再爬一层(在这个当儿补充魔力)才能再次使用瞬移。爬每单位高度需要消耗小炎1 秒时间。 消灭魔女之夜是刻不容缓的,所以小炎想找你帮她找出一种最短时间方案能通往楼顶。
- 输入
- 本题有多组数据,以文件输入结尾结束。
每组数据第一行一个数字N(1 <= N <= 10000),代表楼层数量。
接下去N行,每行一个数字H(1 <= H <= 100),代表本层的高度。 - 输出
- 对于每组数据,输出一行,一个数字S,代表通往楼顶所需的最短时间。
- 样例输入
-
5 3 5 1 8 4
- 样例输出
-
1
1 #include<iostream> 2 #include<algorithm> 3 #include<queue> 4 #include<cstdio> 5 #include<cstring> 6 using namespace std; 7 const int N = 1e4+10; 8 int a[N]; 9 int dp[N][2];//0代表上次跳了,一代表上次调; 10 int main() 11 { 12 int n,ans; 13 while(~scanf("%d",&n)) 14 { 15 memset(dp,0,sizeof(dp)); 16 ans = 0; 17 for(int i=1;i<=n;i++) 18 scanf("%d",&a[i]); 19 dp[1][0] = a[1]; 20 for(int i=2;i<=n;i++) 21 { 22 dp[i][1] = min(dp[i-1][0],dp[i-2][0]);//跳上去 23 dp[i][0] = min(dp[i-1][1]+a[i], dp[i-1][0]+a[i]);//走上来 24 } 25 printf("%d\n",min(dp[n][1],dp[n][0])); 26 } 27 return 0; 28 }