[vijos1235]天堂的饋贈

題目←

狀態定義很顯然的DP題
設dp[i][j]爲第i秒位於位置j所能獲得的最大禮物價值
這樣dp[i][j]可以由dp[i - 1][j - 1],dp[i - 1][j],dp[i - 1][j + 1]推來

一開始怎麼交怎麼wa,鬱悶不已
然後發現是這句話:

當禮物在某一秒末恰好到達小杉所在的格子中,小杉就接到了這個禮物

所以。。所有到達時間是浮點數(速度不被H整除)的禮物都是接不到的……
改了就A了……

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
const int MAXN = 2000 + 50;
int W,P,H,N;
struct zt{
    int t,r,v,s;
    int arr;
}l[MAXN << 1],e[MAXN << 1];
int dp[2500][550];
int last;
bool cmp(zt a,zt b){
    return a.arr < b.arr;
}
int ans1,ans,cnt;
int main(){
    scanf("%d%d%d%d",&W,&P,&H,&N);
    for(int i = 1;i <= N;i ++){
        scanf("%d%d%d%d",&e[i].t,&e[i].r,&e[i].v,&e[i].s);
        e[i].arr = e[i].t + H/e[i].v;
        if(H%e[i].v || e[i].arr < abs(e[i].r - P)){
            ans1 += e[i].s;
        }
        else{
            cnt ++;
            l[cnt] = e[i];
            last = max(last,l[cnt].arr);
        }
    }
    N = cnt;
    sort(l + 1,l + N + 1,cmp);
    memset(dp,-1,sizeof(dp));
    dp[0][P] = 0;
    int p = 1;
    for(int t = 1;t <= last;t ++){
        int v = 0;

        loop: 
        if(t == l[p].arr){
            v = l[p].s;
        }
        for(int j = 1;j <= W;j ++){
            if(j != 1 && dp[t - 1][j - 1] != -1){
                dp[t][j] = max(dp[t][j],dp[t - 1][j - 1] + (j == l[p].r)*v);
            }
            if(j != W && dp[t - 1][j + 1] != -1){
                dp[t][j] = max(dp[t][j],dp[t - 1][j + 1] + (j == l[p].r)*v);
            }
            if(dp[t - 1][j] != -1){
                dp[t][j] = max(dp[t][j],dp[t - 1][j] + (j == l[p].r)*v);
            }
            ans = max(ans,dp[t][j]);
        }
        if(v)p ++;
        if(l[p].arr == l[p - 1].arr)goto loop;
    }
    printf("%d\n%d",ans,ans1);
}

其實有bug,看了題解才意識到
goto是爲了處理同一時刻落下的禮物情況;
但是當同一時刻到達同一位置的禮物不止一個的時候,這個程序只能選擇一個;
處理方法是開數組V[i][j],表示i時刻到達位置j的禮物的價值總和
連goto都免了……

處理後代碼:

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cmath>
using namespace std;
int dp[2500][550],V[2500][550];
int a,b,c,d;
int W,P,H,N;
int ans1,ans2,cnt,last;
int main(){
    scanf("%d%d%d%d",&W,&P,&H,&N);
    for(int i = 1;i <= N;i ++){
        scanf("%d%d%d%d",&a,&b,&c,&d);
        if(H%c || a + H/c < abs(b - P))
            ans2 += d;
        else
            V[a + H/c][b] += d,last = max(last,a + H/c);
    }
    memset(dp,-1,sizeof(dp));
    dp[0][P] = 0;
    for(int i = 1;i <= last;i ++)
    for(int j = 1;j <= W;j ++){
        dp[i][j] = max(max(dp[i - 1][j - 1],dp[i - 1][j + 1]),max(dp[i - 1][j],dp[i][j])) + V[i][j];
        ans1 = max(ans1,dp[i][j]);
    }
    printf("%d\n%d",ans1,ans2);
    return 0;
}
發佈了103 篇原創文章 · 獲贊 11 · 訪問量 2萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章