"DP ring" Naptime

Title Description

Here Insert Picture Description

answer

If this is a linear problem is very simple.

Our most intuitive idea is to set up f [ i ] [ j ] f[i][j] represents the first i i periods, were j j times the maximum rest to recover.

When the self-study found that worth now and what is currently in the state, so we set up f [ i ] [ j ] [ 0 / 1 ] f[i][j][0/1] represents the first i i periods, were the j-th rest with ( 1 1 ) no ( 0 0 ) The maximum recovery value of sleeping or getting ready for bed.

It is easy to deduce the state transition equation:
f [ i ] [ j ] [ 0 ] = m a x ( f [ i 1 ] [ j ] [ 0 ] , f [ i ] [ j ] [ 1 ] ) f[i][j][0]=max(f[i-1][j][0],f[i][j][1])
f [ i ] [ j ] [ 1 ] = m a x ( f [ i 1 ] [ j 1 ] [ 0 ] , f [ i 1 ] [ j 1 ] [ 1 ] + U j ) f[i][j][1]=max(f[i-1][j-1][0],f[i-1][j-1][1]+U_j)
Initialization is f [ 1 ] [ 0 ] [ 0 ] = f [ 1 ] [ 1 ] [ 1 ] = 0 f[1][0][0]=f[1][1][1]=0 Other negative infinity indicates illegal.

answer: m a x ( f [ n ] [ m ] [ 1 ] , f [ n ] [ m ] [ 0 ] ) max(f[n][m][1],f[n][m][0])

If you think about the answers do not deal with the impact brought by the ring: there will ignore the answer there is a link with one of the n junction , let's think about what this contact was.

in case n n not sleep, then n n will not 1 1 impact, transfer can be done in non-annular DP; if n n is sleeping, if at this time 1 1 is not sleep, it may also take into account the non-annular DP state; therefore is only relevant links n n As a preliminary, let 1 1 sleeping directly generate contributions.

Then we can force the n n sleep, 1 1 also produces sleep contribution.

Only need to change the initialization and the target state to: f [ 1 ] [ 1 ] [ 1 ] = U 1 f[1][1][1]=U_1 The rest is negative infinity. answer: f [ n ] [ m ] [ 1 ] . f[n][m][1].

Therefore, in the ring problem, we can think about how you can use some of the special restrictions that the annular problem into linear problem.

code show as below:

#include <bits/stdc++.h> 

using namespace std;
const int N = 4000;

int n, m, ans;
int a[N], f[N][N][2], g[N][N][2];

inline int read(void)
{
    int s = 0, w = 1; char c = getchar();
    while (c < '0' || c > '9') c = getchar();
    while (c >= '0' && c <= '9') s = s*10+c-48, c = getchar();
    return s * w;
} 

void dp(void)
{
	for (int i=2;i<=n;++i)
	{
		f[i][0][0] = 0;
		for (int j=1;j<=m;++j)
			f[i][j][0] = max(f[i-1][j][0],f[i-1][j][1]),
		    f[i][j][1] = max(f[i-1][j-1][0],f[i-1][j-1][1]+a[i]);
	}
	return;
}

int main(void)
{
	freopen("naptime..in","r",stdin);
	freopen("naptime..out","w",stdout);
	n = read(), m = read();
	for (int i=1;i<=n;++i) a[i] = read();
	memset(f,-30,sizeof f);
	f[1][0][0] = 0, f[1][1][1] = 0, dp(), ans = max(f[n][m][0],f[n][m][1]);
	memset(f,-30,sizeof f);
	f[1][1][1] = a[1], dp(), ans = max(f[n][m][1],ans);
	cout << ans << endl;
	return 0;
}

Guess you like

Origin blog.csdn.net/Ronaldo7_ZYB/article/details/92640444