题意:
一个学校要排出n天的课程表,有m个课程,每天有且只能一个课程,给出每个课程需要做的作业量的范围(a[i]——b[i]),和难度。要求n天的课程要按难度递增,并且相邻两天的作业量要满足x[i]=x[i-1]+k或者x[i]=x[i-1]*k。问如何排课程表使得总作业量最大。
题解:
dp[i][j][k]表示到第i天位置,第i天选了j课程,作业量为j+a[i],因为a[i]可以达到10^6,但是b[i]-a[i]不超过100,相当于优化了内存。
接着直接dp就好,需要存下路径,pre[i][j][k] 用结构体,存两个变量一个是选择的课程编号,一个是作业量-a[i]。
这样做数据各种都过,极限数据也过,但是就是wa,四个小时的心酸使。
之后发现排序完序号会乱了,所以加个ID,于是ac了。。。。
#include<iostream>
#include<math.h>
#include<stdio.h>
#include<algorithm>
#include<string.h>
#include<vector>
#include<map>
using namespace std;
typedef long long ll;
const int oo=0x3f3f3f3f;
const ll OO=1LL<<61;
const ll MOD=1000000007;
#define eps 1e-6
#define maxn 55
#define maxm 105
ll dp[maxn][maxn][maxm];
///前i天,第i天选了第j们课,并且第i天的作业量为k+a[i]时,总作业量的最大值。
struct DP
{
ll num,exer;
}pre[maxn][maxn][maxm];
struct SUBJ
{
ll a,b;
int c;
int id;
}sub[maxn];
ll num,exer;
int n,m;
ll k;
bool Dp()
{
memset(dp,-1,sizeof dp);
memset(pre,-1,sizeof pre);
for(int j=1;j<=m;j++)
for(ll x=sub[j].a;x<=sub[j].b;x++)
{
dp[1][j][x-sub[j].a]=x;
}
for(int i=1;i<n;i++)
{
for(int j=1;j<=m;j++)
{
for(ll x=sub[j].a;x<=sub[j].b;x++)
{
if(dp[i][j][x-sub[j].a]==-1)continue;
for(int y=j+1;y<=m;y++)
{
if(sub[y].c<=sub[j].c)continue;
///x表示今天的作业量 x+k表示明天的作业量
if(sub[y].a<=x+k&&x+k<=sub[y].b)
{
if(dp[i+1][y][x+k-sub[y].a]<dp[i][j][x-sub[j].a]+x+k)
{
dp[i+1][y][x+k-sub[y].a]=dp[i][j][x-sub[j].a]+x+k;
pre[i+1][y][x+k-sub[y].a].num=j;
pre[i+1][y][x+k-sub[y].a].exer=x-sub[j].a;
}
}
///x表示今天的作业量 x*k表示明天的作业量
if(sub[y].a<=x*k&&x*k<=sub[y].b)
{
if(dp[i+1][y][x*k-sub[y].a]<dp[i][j][x-sub[j].a]+x*k)
{
dp[i+1][y][x*k-sub[y].a]=dp[i][j][x-sub[j].a]+x*k;
pre[i+1][y][x*k-sub[y].a].num=j;
pre[i+1][y][x*k-sub[y].a].exer=x-sub[j].a;
}
}
}
}
}
}
ll ans=-1;
for(int j=1;j<=m;j++)
{
for(ll x=sub[j].a;x<=sub[j].b;x++)
if(dp[n][j][x-sub[j].a]!=-1&&ans<dp[n][j][x-sub[j].a])
{
ans=dp[n][j][x-sub[j].a];
num=j;
exer=x-sub[j].a;
}
}
return ans!=-1;
}
void output(int day,ll num,ll exer)
{
if(pre[day][num][exer].num==-1)
{
cout<<sub[num].id<<" "<<exer+sub[num].a<<endl;
return ;
}
output(day-1,pre[day][num][exer].num,pre[day][num][exer].exer);
cout<<sub[num].id<<" "<<exer+sub[num].a<<endl;
}
bool cmp(SUBJ s1,SUBJ s2)
{
return s1.c<s2.c;
}
int main()
{
while(cin>>n>>m>>k)
{
for(int i=1;i<=m;i++)
{
cin>>sub[i].a>>sub[i].b>>sub[i].c;
sub[i].id=i;
}
sort(sub+1,sub+1+m,cmp);
if(Dp())
{
puts("YES");
output(n,num,exer);
}
else puts("NO");
}
return 0;
}