51 nod 1636 教育改革(DP)

题目来源:  CodeForces
基准时间限制:1 秒 空间限制:131072 KB 分值: 20  难度:3级算法题
 收藏
 关注

最近A学校正在实施教育改革。

一个学年由n天组成。A学校有m门课程,每天学生必须学习一门课,一门课程必须在一天内学习完。在学习完第i门课程后,学生们会收到  xi  个家庭作业,其中  xi[ai,bi]  。每门课还有一个属性,就是复杂度  ci  。A学校现在要制他们的课程表,具体要求如下:

·在课程表中,随着天数的增加,课程的复杂度是严格递增的。

·除了第1天,每天的作业量必须是前一天的k倍,或者比前一天多k个作业。(假设第i天的作业量为  xi  ,则对于i(1<i≤n)到满足  xi  k+xi1  或  xi  kxi1  );

现在,给定天数n,系数k,和m门课程的ai,bi,ci(1≤i≤m)。要求计算一个学年可以安排最大的总作业量(  ni=1xi  )是多少。


Input
单组测试数据
第一行,三个由空格隔开的整数n,m,k(1≤n≤m≤50,1≤k≤100),表示一个学年的天数,课程的数量,和作业增量系数。
接下来的m行,
每行有三个整数,ai,bi,ci(1≤ai≤bi≤10^16,bi-ai≤100,1≤ci≤100)
分别表示第i门课程的最小作业量,和最多作业量,以及复杂度。
不同的课程可以有相同的复杂度。课程编号从1到m。
Output
如果有可行方案,第一行输出“YES”(没有引号),第二行输出最大的作业量。
如果没有可行方案,则输出一行“NO”(没有引号)。
Input示例
4 5 2
1 10 1
1 10 2
1 10 3
1 20 4
1 100 5
Output示例
YES
78

这题主要有一个把差值当做一维数组的奇技淫巧

#include <cstdio>
#include <algorithm>
#include <cstdlib>
#include <bits/stdc++.h>
typedef long long LL;
const int N =1e4+100;
using namespace std;
LL dp[51][51][110];
struct node
{
    LL l, r, c;
    bool operator <(const node &A)const
    {
        return c<A.c;
    }
} p[N];

int main()
{
    memset(dp,-1,sizeof(dp));
    LL n, m, k1;
    scanf("%lld %lld %lld", &n, &m, &k1);
    for(int i=0; i<m; i++)
        scanf("%lld %lld %lld", &p[i].l,&p[i].r,&p[i].c);
    sort(p,p+m);
    for(int i=0; i<m; i++)
    {
        for(int j=0; j<=p[i].r-p[i].l; j++)
        {
            dp[1][i][j]=j+p[i].l;
        }
    }

    for(int i=2; i<=n; i++)
    {
        for(int j=0; j<m; j++)
        {
            for(int k=0; k<=p[j].r-p[j].l; k++)
            {
                for(int q=0; q<j&&p[q].c<p[j].c; q++)
                {
                    LL tmp=p[j].l+k-k1;
                    if(tmp>=p[q].l&&tmp<=p[q].r&&dp[i-1][q][tmp-p[q].l]!=-1)
                    {
                        dp[i][j][k]=max(dp[i][j][k],dp[i-1][q][tmp-p[q].l]+tmp+k1);
                    }
                    tmp+=k1;
                    if(tmp%k1==0&&(tmp/k1)>=p[q].l&&(tmp/k1)<=p[q].r&&dp[i-1][q][tmp/k1-p[q].l]!=-1)
                    {
                        dp[i][j][k]=max(dp[i][j][k],dp[i-1][q][tmp/k1-p[q].l]+tmp);
                    }
                }
            }
        }
    }

    LL ans=-1;
    for(int i=0; i<m; i++)
    {
        for(int j=0;j<=p[i].r-p[i].l;j++)
        {
            ans=max(ans,dp[n][i][j]);
        }
    }
    if(ans==-1)puts("NO");
    else
    {
        puts("YES");
        cout<<ans<<endl;
    }
    return 0;
}








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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值