【51Nod - 1636】教育改革【DP】

题目

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

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

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

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

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

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”(没有引号)。
Sample Input
4 5 2
1 10 1
1 10 2
1 10 3
1 20 4
1 100 5
Sample Output
YES
78

渣渣题解

这个题就是一个DP,但是DP不好的我首先想到了定义dp[i]表示作业量为i最多上dp[i]节课,然后暴力O(n)找答案.嘿嘿嘿,时空都会炸,优化优化dp[i][j]表示上了i节课布置的作业总量为j是否可行但是这样空间炸了,于是蒟蒻又想,如果有作业量,空间会炸,我想想没有作业量这一维,dp[i][j]表示上了i节课,最后一节是j的最大作业量,空间不炸了,但是我不知道怎么推了。还是加上作业量这一维吧,于是就有新的状态再记录一个作业量,dp[i][j][k]表示上了i节课,最后一节是j,j的作业量是k,的最大作业量,如果这样,那么
dp[i][j][l]=max(dp[i][j][l],dp[i-1][o][l-k],dp[i-1][o][l/k] ( l%k==0));
(i-1<=o< j),
空间还是炸了,但是这个题有一个神奇的地方,bi-ai≤100,也就是说空间中0-ai,bi-10^16没有用,所以我们将l定义为ai+l,l就小于等于100了,这样就开的下了

代码

#include<cstdio>
#include<cstring>
#include<algorithm>
#include<vector>
#include<queue>
using namespace std;
const long long MAXN=55,MAXM=105;
long long dp[MAXN][MAXN][MAXM];
long long n,m,k;
struct le
{
    long long a,b,c;
}a[MAXN];
bool cmp(le a,le b)
{
    return a.c<b.c;
}
int main()
{
    scanf("%I64d %I64d %I64d",&n,&m,&k);
    for(long long i=1;i<=m;i++)
    {
        scanf("%I64d %I64d %I64d",&a[i].a,&a[i].b,&a[i].c);
    }
    sort(a+1,a+m+1,cmp);
    memset(dp,-1,sizeof(dp));  
    for(long long j=1;j<=m;j++)
        for(long long l=0;l<=a[j].b-a[j].a;l++)
            dp[1][j][l]=l+a[j].a;
    for(long long i=2;i<=n;i++)
    {
        for(long long j=i;j<=m;j++)
        {
            for(long long l=0;l<=a[j].b-a[j].a;l++)
            {
                for(long long o=i-1;o<j;o++)
                {
                    long long cc=l+a[j].a;
                    if(a[o].a<=cc-k&&cc-k<=a[o].b&&dp[i-1][o][cc-k-a[o].a]!=-1&&a[j].c!=a[o].c)
                        dp[i][j][l]=max(dp[i-1][o][cc-k-a[o].a]+cc,dp[i][j][l]);
                    if(cc%k==0&&a[o].a<=cc/k&&cc/k<=a[o].b&&dp[i-1][o][cc/k-a[o].a]!=-1&&a[j].c!=a[o].c)
                        dp[i][j][l]=max(dp[i-1][o][cc/k-a[o].a]+cc,dp[i][j][l]);
                }
            }
        }
    }
    long long ans=-1;
    for(long long j=n;j<=m;j++)
        for(long long l=0;l<=a[j].b-a[j].a;l++)
            ans=max(ans,dp[n][j][l]);
    if(ans==-1)
        printf("NO\n");
    else
        printf("YES\n%I64d\n",ans);
}

这个题还有比较坑的地方(至少蒟蒻认为),由于题目要求要难度要严格上升所以还要特判难度相同的时候不能转移(wa在29/30).

猜你喜欢

转载自blog.csdn.net/qq_35713030/article/details/79318690
今日推荐