题解
- 可以发现,ID[i]对答案的贡献只有ID[i+1],可以考虑dp
- 设f[i][j]为前i个位置,第i个位置选j的最大sum值
- 显然得出f[i][j]=max(f[i-1][k]+a[min(j,k)]-a[min(j,k+1])
- 考虑一下如果得出移动后r的位置
- x=((x-(i-1)*r)%n+n)%n
- 然后再定义一个g[i][j]统计f[i][j]是选了那个数转换来的
- 考虑两种情况k <= j,这时f[i][j]=max(f[i-1][k]+a[k]-a[j+1],f[i][j])
-
如果k > j,这时f[i][j]=max(f[i-1][k]+a[j]-a[k+1],f[i][j])
那么这样O(N^3),感觉时间有点虚
考虑一下如果弄掉一个N
我们可以正着跑一遍,再反着跑一遍,再判断是否合法,合法求最大值,记录g[i][j]
代码
1 #include<cstdio>
2 #include<iostream>
3 #include<cstring>
4 using namespace std;
5 const int inf=2147483647;
6 int n,r,a[3010],f[3010][3010],g[3010][3010];
7 void out(int x,int y)
8 {
9 if (x!=0) out(x-1,g[x][y]);
10 printf("%d ",y+1);
11 }
12 int main()
13 {
14 memset(f,200,sizeof(f));
15 memset(f[0],0,sizeof(f[0]));
16 scanf("%d%d",&n,&r);
17 for (int i=0;i<=n-1;i++) scanf("%d",&a[i]);
18 for (int i=1;i<=n;i++)
19 {
20 int ans=-inf,num;
21 for (int j=0;j<=n-2;j++)
22 {
23 if (f[i-1][j]+a[((j-(i-1)*r)%n+n)%n]>ans)
24 {
25 ans=f[i-1][j]+a[((j-(i-1)*r)%n+n)%n];
26 num=j;
27 }
28 if (ans-a[((j+1-(i-1)*r)%n+n)%n]>f[i][j])
29 {
30 f[i][j]=ans-a[((j+1-(i-1)*r)%n+n)%n];
31 g[i][j]=num;
32 }
33 }
34 ans=-inf;
35 for (int j=n-2;j>=0;j--)
36 {
37 if (f[i-1][j]-a[((j+1-(i-1)*r)%n+n)%n]>ans)
38 {
39 ans=f[i-1][j]-a[((j+1-(i-1)*r)%n+n)%n];
40 num=j;
41 }
42 if (ans+a[((j-(i-1)*r)%n+n)%n]>f[i][j])
43 {
44 f[i][j]=ans+a[((j-(i-1)*r)%n+n)%n];
45 g[i][j]=num;
46 }
47 }
48 }
49 int ans=-inf,num;
50 for (int j=0;j<=n-2;j++)
51 if (f[n][j]>ans)
52 {
53 ans=f[n][j];
54 num=j;
55 }
56 printf("%d
",ans);
57 out(n,num);
58 }