#90 C

problem link http://codeforces.com/contest/119/problem/C

A classic dp problem, even though I knew this I still spent much time on figuring out the solution.

As solving most dp problem, the difficult point is to find out the state transition equation.

Before working on the state transition equation, I need to realize what is the optimum condition, and the problem has

told me, the maximal possible amount of homework ( poor students. )

At first glance, I have found the first state: pick the Mth course at Nth day. 

But this is far from the complete state of dp, the key is how many homework of all courses should issue at N-1th day ?

Thanks to this forward thinking, I couldn't find the answer for about 2 hours.

The amount of homework which course i can issue is range from A[i] to B[i], and the problem has given me this data.

By backward thinking, for every possible course M in Nth day (some course can never be set to Nth day),

I need to know what is the maximal amount of homework when course M issue every possible amount of homework ( A[i] to B[i], the problem mentions that B[i] - A[i] <= 100, so enumeration is acceptable )

For example, I need to know the total amount of homework when course m in day n issues x homework, if that value is maximal, then I will pick these combination( day n, course m, issue x). according to the constraint given by the problem, there must be x - K or x/K homework issued at n-1 day by some other courses.

The above example is the key to find the state transition equation. ( But I have spent much time on expressing such example, stupid.. )

dp[n][m][x] = max{ every other courses m' | dp[n-1][m'][x-K] , dp[n-1][m'][x/K] } + x

Other constraint condition just some filters to state transition equation, no big deal.

#include <stdio.h>
#include <stdlib.h>

#define MAX_N 51
#define MAX_M 51
#define MAX_LEN 101

typedef struct path_info_st {
int m;
long long ht;
} path_info_st, *path_info_t;

long long A[MAX_M], B[MAX_M];
int C[MAX_M], L[MAX_M];
long long dp[MAX_N][MAX_M][MAX_LEN];
long long help1[MAX_M][MAX_LEN];
long long help2[MAX_M][MAX_LEN];
path_info_st path_data[MAX_N][MAX_M][MAX_LEN];
path_info_t path[MAX_N];
bool can_pick[MAX_N][MAX_M];
bool can_pick2[MAX_N][MAX_M][MAX_LEN];
int N, M, K;

int main() {
long long i, j, k, r, p, q, t, t1, t2, t3, t4, t5, t6;
scanf("%d %d %d", &N, &M, &K);
for( i=0;i<M;i++ )
scanf("%I64d %I64d %d", &(A[i]), &(B[i]), &(C[i]));
for( i=0;i<M;i++ )
L[i] = (int)(B[i] - A[i]);

for( i=0;i<M;i++ ) {
t = L[i];
t1 = A[i];

for( j=0;j<=t;j++ ) {
t2 = t1 + j;
help1[i][j] = t2 / K;
}

for( j=0;j<=t;j++ ) {
t2 = t1 + j;
help2[i][j] = t2 - K;
}
}

for( i=0;i<M;i++ ) {
t1 = A[i];
t = L[i];
for( j=0;j<=t;j++ )
dp[0][i][j] = t1 + j;

can_pick[0][i] = true;
}

for( i=1;i<N;i++ ) {
for( j=0;j<M;j++ ) {
t = L[j];
t1 = A[j];
for( k=0;k<M;k++ ) {
if( C[k] < C[j] && can_pick[i-1][k] ) {
t3 = A[k];
t4 = B[k];
for( r=0;r<=t;r++ ) {
t2 = t1 + r;
p = help1[j][r];
q = help2[j][r];
if( p >= t3 && p <= t4 && (t2 % K) == 0 ) {
t5 = dp[i][j][r];
t6 = dp[i-1][k][p-t3];
if( t6 > 0 && (0 == t5 || t5 < t2 + t6) ) { // t6 > 0 means there is a path to i-1 day set subject k and issues total t6 home task
dp[i][j][r] = t2 + t6;
path_data[i][j][r].m = k;
path_data[i][j][r].ht = p-t3;
can_pick[i][j] = true;
}
}
if( q >= t3 && q <= t4 ) {
t5 = dp[i][j][r];
t6 = dp[i-1][k][q-t3];
if( t6 > 0 && ( 0 == t5 || t5 < t2 + t6 ) ) { // t6 > 0 means there is a path to i-1 day set subject k and issues total t6 home task
dp[i][j][r] = t2 + t6;
path_data[i][j][r].m = k;
path_data[i][j][r].ht = q-t3;
can_pick[i][j] = true;
}
}
}
}
}
}
}

k = 0;
for( i=0;i<M;i++ ) {
t = L[i];
for( j=0;j<=t;j++ ) {
t2 = dp[N-1][i][j];
if( k < t2 ) {
k = t2; t3 = i; t4 = j;
}
}
}

if( 0 == k ) {
printf("NO\n");
return 0;
}

k = 0, i = 1;
printf("YES\n");
if( N > 1 ) {
path_info_t pi = &(path_data[N-1][t3][t4]);
for( i=1;i<N-1;i++ ) {
path[k++] = pi;
pi = &(path_data[N-i-1][pi->m][pi->ht]);
}
path[k++] = pi;

for( i=k-1;i>=0;i-- )
printf("%d %I64d\n", (int)(path[i]->m + 1), (path[i]->ht + A[path[i]->m]));
}
printf("%d %I64d\n", (int)(t3 + 1), (t4 + A[t3]));

return 0;
}

The most disgusting part of my code is recording the path info, and use it for backward tracing.

你可能感兴趣的:(c)