【DP】SRM642 D1L2(TopCoder - 13319) —— TaroCutting

题目传送门

稍微有点思维难度的DP

首先可以明确一个性质,每棵树只会被砍一次.假设砍两次,那么完全可以第一次不砍,第二次砍,这样做是不会影响答案的.同时可以看出,树的生长速度对答案的影响比树初始的高度大.

不妨利用一下贪心的思想,将生长速度最快的树,放到最后一天用dev值最小的机器砍它.
因此我们将树按照生长速度降序排序,将机器按dev值升序排序.
然后从最后一天开始DP
d[i][j][k]表示在T-i到i天,砍了前j棵树,且用了前k个机器.
转移分为两种,这棵树一直不砍和现在砍这棵树.详见代码

有几点需要注意一下,1.如果树的高度不够某个机器的dev,实际上是不会对答案进行影响的,因为不满足最优性.2.机器是每一天都可以用一次,注意将上一天的状态转移到这一天的k来.

#include<cstdio>
#include<cstring>
#include<vector>
#include<algorithm>
using namespace std;

const int MAXN=155;
const int INF=0x3f3f3f3f;

struct node{
    int h,a;
    bool operator < (const node &p) const{
        return a<p.a;
    }
}t[MAXN];
int dp[MAXN][MAXN][MAXN];

class TaroCutting {
public:
    int getNumber(vector <int> h,vector <int> a,vector <int> dev,int T){
        int n=h.size(),m=dev.size();
        memset(dp,0x3f,sizeof dp);
        sort(dev.begin(),dev.end());
        dp[0][0][0]=0;
        for(int i=0;i<n;i++)
            t[i].h=h[i],t[i].a=a[i];
        sort(t,t+n);
        h.clear(),a.clear();
        for(int i=0;i<n;i++) h.push_back(t[i].h),a.push_back(t[i].a);
        for(int i=0;i<T;i++)
            for(int j=0;j<=n;j++)
                for(int k=0;k<=m;k++){
                    dp[i+1][j][0]=min(dp[i+1][j][0],dp[i][j][k]);
                    if(j<n) dp[i][j+1][k]=min(dp[i][j+1][k],dp[i][j][k]+h[j]+T*a[j]);
                    if(k<m&&j<n)
                        dp[i][j+1][k+1]=min(dp[i][j+1][k+1],dp[i][j][k]+dev[k]+i*a[j]);
                }
        return dp[T][n][0];
    }
};

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值