Description
假定给出一个包含N个整数的数组A,包含N+1个整数的数组ID,与整数R。其中ID数组中的整数均在区间[1,N-1]中。
用下面的算法对A进行Warshall-Turing-Fourier变换(WTF):
将数组A往右循环移动R位
给出数组A以及整数R,但没有给出数组ID。在对数组A进行了WTF算法后,变量sum的可能出现的最大值数多少?
用下面的算法对A进行Warshall-Turing-Fourier变换(WTF):
sum = 0
for i = 1 to N
index = min{ ID[i], ID[i+1] }
sum = sum + A[index]
将数组A往右循环移动R位
将数组A内所有的数取相反数
for i = 1 to N
index = max{ ID[i], ID[i+1] }
index = index + 1
sum = sum + A[index]
给出数组A以及整数R,但没有给出数组ID。在对数组A进行了WTF算法后,变量sum的可能出现的最大值数多少?
Input
第一行包含两个整数N与R。
第二行包含N个整数,代表A[1]到A[N]的值。
第二行包含N个整数,代表A[1]到A[N]的值。
Output
第一行输出变量sum可能出现的最大值。
第二行输出此时的ID数组,包含N+1个整数。必须满足ID数组中每一个数均在区间[1,N-1]中。若有多个满足的ID数组,输出任意一组。
如果第一行是正确的(不管有没有输出第二行),你能得到该测试点50%的得分。
第二行输出此时的ID数组,包含N+1个整数。必须满足ID数组中每一个数均在区间[1,N-1]中。若有多个满足的ID数组,输出任意一组。
如果第一行是正确的(不管有没有输出第二行),你能得到该测试点50%的得分。
Sample Input
输入1:
5 3
1 -1 1 -1 1
输入2:
6 5
2 5 4 1 3 5
Sample Output
输出1:
10
1 1 1 2 2 3
输出2:
16
3 2 1 1 5 4 1
Data Constraint
对于20%的数据,N<=7。
对于60%的数据,N<=300。
对于100%的数据,2<=N<=3000, 1<=R<N, -10000<=A[i]<=10000。
对于60%的数据,N<=300。
对于100%的数据,2<=N<=3000, 1<=R<N, -10000<=A[i]<=10000。
题解
- 可以发现,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 }