Bzoj3628: [JLOI2014]天天酷跑

3628: [JLOI2014]天天酷跑

Time Limit: 20 Sec  Memory Limit: 128 MB
Submit: 121  Solved: 44
[Submit][Status][Discuss]

Description

在游戏天天酷跑中,最爽的应该是超级奖励模式了吧,没有一切障碍,可以尽情的吃金币,现在请你控制游戏角色来获得尽可能多的分数。
游戏界面离散为一个长度为1~n,高度为1~m(初始点为(0,1))的矩阵图。每个格子上都有收益(-1~1000),-1表示该点不能通过。游戏角色从起点一路奔跑向终点,中途可以跳跃来获得更高的分数,在空中还能进行连跳。游戏开始前你可以设定跳跃的高度,以及能连跳的次数,初始跳跃高度为1,连跳数为1(最多为5),升级跳跃高度和连跳都需要一定的花费。跳跃高度设定完后游戏角色每次跳跃高度都将固定,连跳必须在下落过程中可以使用。所有操作都将在整点上完成,需要保证设定完的跳跃高度及连跳数,无法跳出游戏高度上限。
 

以下是连跳数为2连跳,跳跃高度为2的跳跃方案:

Input

第一行四个整数n,m,cost1,cost2。n,m如题意所示,cost1,cost2分别表示每升一级跳跃高度,连跳数所需的花费。

接下来m行,每行n个数。第i行第j个数表示地图中高度为i,长度在第j列处的收益。

Output

如果无法跑出终点线,就输出“mission failed”,否则输出一行三个数,分别表示最大收益;及最大收益时,最小的连跳数;最大收益,最小连跳数时,最小的跳跃高度。

Sample Input

7 4 6 10
9 4 7 7 4 3 2
18 8 9 4 15 12 4
19 2 4 7 10 18 12
8 1 13 14 16 0 14

Sample Output

67 1 2

HINT

提示

20%数据满足 m=2, n<=100000;

另有80%数据 n<=10000,2<m<=20,其中20%数据 2<n<=10,m<=10;

/*
    定义状态f[i][j][o]表示处于x,y这个位置,还剩余o次连跳数的最大收益
    如果是跑——f[i][j][o]=max(f[i][j+1][o]+w[i][j]) w[i][j]为这点的权值;
    如果是跳的话——f[i][j][o]=max(f[i+跳跃高度(high)][j+high][o--]+hhh+w[i][j]) hhh跳跃上升过程中得到的金币数。
*/
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<iostream>
using namespace std;
#define inf 1<<30
#define maxn 100010
bool vis[25][maxn][6];
int f[25][maxn][6],map[25][maxn];
int n,m,c1,c2,ans=-inf,ans1,ans2,h,num;
int dfs(int x,int y,int now){
    if(x>n)return 0;
    if(map[y][x]==-1)return -inf;
    if(vis[y][x][now])return f[y][x][now];
    int tot=-inf,sum=0;bool flag=1;
    if(y==1)now=0;
    if(now<num){
        for(int i=1;i<h;i++){
            if(map[y+i][x+i]==-1){flag=0;break;}
            sum+=map[y+i][x+i];
        }
        if(flag)tot=max(tot,sum+dfs(x+h,y+h,now+1));
    }
    if(y==1)tot=max(tot,dfs(x+1,y,0));
    if(y>1)tot=max(tot,dfs(x+1,y-1,now));
    vis[y][x][now]=1;
    f[y][x][now]=tot+map[y][x];
    return f[y][x][now];
}
int main(){
    scanf("%d%d%d%d",&n,&m,&c1,&c2);
    for(int i=1;i<=m;i++)
        for(int j=1;j<=n;j++)
            scanf("%d",&map[i][j]);
    for(num=1;num<=5;num++){
        for(h=1;h*num<m;h++){
            memset(f,-1,sizeof(f));
            memset(vis,0,sizeof(vis));
            int tot=dfs(0,1,m)-c2*(num-1)-c1*(h-1);
            if(ans<tot)ans=tot,ans1=num,ans2=h;
        }
    }
    if(ans>0)printf("%d %d %d",ans,ans1,ans2);
    else printf("mission failed");
    return 0;
}

 

posted @ 2017-09-06 15:51  Echo宝贝儿  阅读(362)  评论(0编辑  收藏  举报