P1095 守望者的逃离

先用了贪心吧这个题 A 了,然后来考虑 dp 怎么做

先说贪心,其中 s1 表示走路的距离, s2 表示闪现了多远

s2 相当于只闪现,没蓝了就原地回蓝

但 s1 是两者兼备的,如果闪现的距离更远,就将 s1 覆盖为 s2

#include<iostream>
#include<cstdio>
#include<cstring>
//#define t time
#define NUM 100000010
#define ll long long
using namespace std;
ll m,s,t;
ll s1,s2,ans;
signed main(){
    ios::sync_with_stdio( false );
    cin >> m >> s >> t;
    while( s1 < s ){
        s1 += 17;
        if( m >= 10 ){
            s2 += 60;
            m -= 10;
        }else m += 4;
        s1 = max(s1,s2);
        ans++;
        if( ans >= t ) break;
    }
    if( s1 >= s ) printf( "Yes\n%lld",ans );
    else printf( "No\n%lld",s1 );
    return 0;
}

 上面是贪心的做法,dp 的话其实跟这个差不多

开一个 dp[i] 存第 i 秒的最远距离,

然后相当于贪心了,如果能闪现就闪现,跑步更优就跑步


还有一种做法,是看题解了,正儿八经的 dp

但是时间会超,想看就看看吧

设dp[i] [j] [1/0] 在第i秒时,魔法值为j,
0代表是由前一秒恢复得到的j,1代表不是恢复得到的j

则dp[i] [j] [0/1] 代表在第i秒时,魔法值为j,
是否是由恢复得到的j 所能跑到的最远距离

然后我们可以推出状态转移方程

先假设使用跳跃技能 dp[i] [j] [1]=max(dp[i-1] [j+10] [1]+60,dp[i-1] [j+10] [0]+60);

第i秒时魔法为j并且不是恢复的来的j(那么只能是由上一次消耗得来) 

所以为第i-1秒法力值为j+10秒时候0/1两个状态得来,
并且此种情况的条件为j+10<=m+1 为什么是m+1可以好好想一想

然后就是假设不用跳跃技能的最大值:
dp[i] [j] [1]=max(dp[i] [j] [1],dp[i-1] [j][1]+17); 
dp[i] [j] [1]=max(dp[i] [j] [1],dp[i-1][j] [0] +17);

然后就是0的情况,是由恢复法力得来的 j 
那么状态转移方程式为:
if(j>=4) dp[i] [j] [0]=max(dp[i-1][j-4] [1],dp[i-1] [j-4] [0]);

但是由于空间相当的大,我们要换成滚动数组

但是不开O2还是会T两个点
转移方程与解释

 

 1 #include<bits/stdc++.h>
 2 using namespace std;
 3 int M,S,T,MAXN;
 4 int t;
 5 //dp[i][j][1/0] 在第i秒 ,魔法值为j  0代表是否是恢复得到的j,1代表不是恢复得到的j  是否跑的最远距离 
 6 int dp[2][1010][2]; 
 7 
 8 int main(){
 9     cin>>M>>S>>T;  //输入 
10     for(int i=1;i<=T;i++){      
11         for(int j=M;j>=1;j--){
12             if(j+10<=M+1) dp[i%2][j][1]=max(dp[(i-1)%2][j+10][1]+60,dp[(i-1)%2][j+10][0]+60); 
13             dp[i%2][j][1]=max(dp[i%2][j][1],dp[(i-1)%2][j][1]+17);
14             dp[i%2][j][1]=max(dp[i%2][j][1],dp[(i-1)%2][j][0]+17);
15             if(j>=4) dp[i%2][j][0]=max(dp[(i-1)%2][j-4][1],dp[(i-1)%2][j-4][0]);
16             MAXN=max(MAXN,dp[i%2][j][1]);
17             MAXN=max(MAXN,dp[i%2][j][0]);
18             if(MAXN>=S&&t==0) t=i; 
19         }
20     }
21     
22     if(MAXN<S){
23         cout<<"No"<<endl<<MAXN;
24     }
25     else{
26         cout<<"Yes"<<endl;
27         cout<<t;
28     }
29 }
代码

 

posted @ 2021-09-25 19:41  little_sheep_xiaoen  阅读(48)  评论(0编辑  收藏  举报