Light OJ 1106 Gone Fishing (DP)

75 篇文章 0 订阅

解析:由于路径的输出要求,这里使用逆推的方式更加合适。

设dp[i][j]为从i开始,剩余时间为j的最大捕鱼量。

枚举在第i个湖上钓鱼的时间k,则有dp[i][j] = max(dp[i+1][j-k]+k时间内能钓到的鱼的数量)


[code]:

#include<cstdio>
#include<cstring>
#include<algorithm>

using namespace std;

int n,m,f[30],d[30],t[30],dp[30][200],pr[30][200];
int tim[30],top;

void init(){
    memset(dp,-1,sizeof(dp));
    memset(pr,-1,sizeof(pr));
    int num,j;
    for(j=0;j<=m;j++){
        num = d[n-1]?min(j,(f[n-1]-1)/d[n-1]+1):j;
        dp[n-1][j] = num*(2*f[n-1]-(num-1)*d[n-1])/2;
    }
}

int main(){
    int i,j,k,cas;
    scanf("%d",&cas);
    for(int T=1;T<=cas;T++){
        scanf("%d%d",&n,&m);
        m *= 12;
        for(i = 0;i < n;i++) scanf("%d",&f[i]);
        for(i = 0;i < n;i++) scanf("%d",&d[i]);
        for(i = 0;i < n-1;i++) scanf("%d",&t[i]);

        init();
        int num,tmp;
        for(i = n-2;i >= 0;i--){
            for(j = 0;j <= m;j++){
                num = d[i]?min(j,(f[i]-1)/d[i]+1):j;
                dp[i][j] = num*(2*f[i]-(num-1)*d[i])/2;
                for(k = j;k >= t[i];k--){
                    num = d[i]?min(k-t[i],(f[i]-1)/d[i]+1):(k-t[i]);
                    tmp = dp[i+1][j-k]+num*(2*f[i]-(num-1)*d[i])/2;
                    if(dp[i][j] < tmp){
                        dp[i][j] = tmp;
                        pr[i][j] = j-k;
                    }
                }
            }
        }
        printf("Case %d:\n",T);
        int t1,t2;
        t1 = 0,t2 = m;top = 0;
        while(t2 != -1){
            tim[top++] = t2 - (pr[t1][t2]==-1?0:(pr[t1][t2]+t[t1]));
            t2 = pr[t1][t2];
            t1++;
        }
        for(;t1 < n;t1++) tim[top++] = 0;
        for(i = 0;i < top;i++){
            if(i) printf(", ");
            printf("%d",tim[i]*5);
        }
        printf("\nNumber of fish expected: %d\n",dp[0][m]);
    }

    return 0;
}


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值