bzoj3628: [JLOI2014]天天酷跑 题目链接 题解 代码

bzoj3628: [JLOI2014]天天酷跑

题解

开始读错题目了,尴尬
由于题目说的跳跃次数和高度是在一开始设定的。
发现枚举一下记忆化搜索就可以过了
要注意,跳到最高点是可以不下坠继续连跳的
另外,上边界不能到达

代码

#include<cstdio> 
#include<cstring> 
#include<algorithm> 
inline int read() { 
    int x = 0,f = 1; 
    char c = getchar(); 
    while(c < '0' || c > '9'){if(c == '-') f = -1; c = getchar(); } 
    while(c <= '9' && c >= '0') x = x * 10 + c - '0',c = getchar(); 
    return x * f; 
} 
const int maxn = 100007; 
int n,m,c1,c2,h,freq; 
#define INF 100000007
int a[23][maxn]; 
int f[23][maxn][6]; 
bool vis[23][maxn][6]; 
int dfs(int x,int y,int jumpcnt) { 
    if(y > n) return 0; 
    if(a[x][y] == -1) return  -INF; 
    if(vis[x][y][jumpcnt]) return f[x][y][jumpcnt]; 
    if(x == 1)jumpcnt = 0; 
    int tmp = -INF ;  
    if(jumpcnt < freq) { 
        int Sum = 0,tx = x,ty = y; bool can = true; 
        for(int i = 1;i < h;i ++) { 
            tx ++,ty ++; 
            if(a[tx][ty] == -1) {can = false; break; } Sum += a[tx][ty];
        } 
        if(can) tmp = std::max(tmp,Sum + dfs(tx + 1,ty + 1,jumpcnt + 1)); 
    } 
    if(x == 1) tmp = std::max(tmp, dfs(x,y + 1,0)) ; 
    if(x > 1) tmp = std::max(tmp, dfs(x - 1,y + 1,jumpcnt)); 
    f[x][y][jumpcnt] = tmp + a[x][y]; 
    vis[x][y][jumpcnt] = true;  
    return f[x][y][jumpcnt];  
} 
int ans = -INF ,an1,an2; 
int main() { 
    n = read(),m = read(), c1 = read(),c2 = read(); 
    for(int i = 1;i <= m;++ i) for(int j = 1;j <= n;++ j) 
        a[i][j] = read(); 
    for(freq = 1;freq <= 5;++ freq) 
        for(h = 1;h * freq < m;++ h) { 
            memset(vis,0,sizeof vis); 
            memset(f,0,sizeof f); 
            int sum = dfs(1,0,m) - (h - 1) * c1 - (freq - 1) * c2; 
            if(sum > ans) ans = sum , an1 = h, an2 = freq; 
        } 
    if(ans > 0) printf("%d %d %d
",ans,an2,an1); 
    else puts("mission failed"); 
    return 0 ; 
}  #include<cstdio> 
#include<cstring> 
#include<algorithm> 
inline int read() { 
    int x = 0,f = 1; 
    char c = getchar(); 
    while(c < '0' || c > '9'){if(c == '-') f = -1; c = getchar(); } 
    while(c <= '9' && c >= '0') x = x * 10 + c - '0',c = getchar(); 
    return x * f; 
} 
const int maxn = 100007; 
int n,m,c1,c2,h,freq; 
#define INF 100000007
int a[23][maxn]; 
int f[23][maxn][6]; 
bool vis[23][maxn][6]; 
int dfs(int x,int y,int jumpcnt) { 
    if(y > n) return 0; 
    if(a[x][y] == -1) return  -INF; 
    if(vis[x][y][jumpcnt]) return f[x][y][jumpcnt]; 
    if(x == 1)jumpcnt = 0; 
    int tmp = -INF ;  
    if(jumpcnt < freq) { 
        int Sum = 0,tx = x,ty = y; bool can = true; 
        for(int i = 1;i < h;i ++) { 
            tx ++,ty ++; 
            if(a[tx][ty] == -1) {can = false; break; } Sum += a[tx][ty];
        } 
        if(can) tmp = std::max(tmp,Sum + dfs(tx + 1,ty + 1,jumpcnt + 1)); 
    } 
    if(x == 1) tmp = std::max(tmp, dfs(x,y + 1,0)) ; 
    if(x > 1) tmp = std::max(tmp, dfs(x - 1,y + 1,jumpcnt)); 
    f[x][y][jumpcnt] = tmp + a[x][y]; 
    vis[x][y][jumpcnt] = true;  
    return f[x][y][jumpcnt];  
} 
int ans = -INF ,an1,an2; 
int main() { 
    n = read(),m = read(), c1 = read(),c2 = read(); 
    for(int i = 1;i <= m;++ i) for(int j = 1;j <= n;++ j) 
        a[i][j] = read(); 
    for(freq = 1;freq <= 5;++ freq) 
        for(h = 1;h * freq < m;++ h) { 
            memset(vis,0,sizeof vis); 
            memset(f,0,sizeof f); 
            int sum = dfs(1,0,m) - (h - 1) * c1 - (freq - 1) * c2; 
            if(sum > ans) ans = sum , an1 = h, an2 = freq; 
        } 
    if(ans > 0) printf("%d %d %d
",ans,an2,an1); 
    else puts("mission failed"); 
    return 0 ; 
}