[dp] Jzoj P4262 WTF交换
题解
- 可以发现,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\n",ans); 57 out(n,num); 58 }