Jzoj P4262 WTF交换___dp

题目大意:

假定给出一个包含 N 个整数的数组 A ,包含 N + 1 个整数的数组 I D ,与整数 R 。其中 I D 数组中的整数均在区间 [ 1 , N 1 ] 中。
用下面的算法对 A 进行 W a r s h a l l T u r i n g F o u r i e r 变换( W T F ):

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位

给出数组 A 以及整数 R ,但没有给出数组 I D
在对数组 A 进行了 W T F 算法后,变量 s u m 的可能出现的最大值数多少?

2 <= N <= 3000 , 1 <= R < N , 10000 <= A [ i ] <= 10000

分析:

被毒瘤题暴奶
可以发现, I D [ i ] 对答案的贡献只有 I D [ i + 1 ] ,可以考虑dp
f [ i ] [ j ] 为前 i i d ,第 i 个位置选数 j 作为 I D [ i ] 的最大 S u m
可以推出
f [ i ] [ j ] = m a x ( f [ i 1 ] [ k ] + a [ m i n ( j , k ) ] a [ m i n ( j , k + 1 ] )
a [ x ] 是已经位移好了的,
x = ( ( x ( i 1 ) r ) m o d n + n ) m o d n
定义 g [ i ] [ j ] 表示 f [ i ] [ j ] 是由哪个数转换而来
考虑两种情况
k <= j , 则 f [ i ] [ j ] = m a x ( f [ i ] [ j ] , f [ i 1 ] [ k ] + a [ k ] a [ j + 1 ] )
k > j , 则 f [ i ] [ j ] = m a x ( f [ i ] [ j ] , f [ i 1 ] [ k ] + a [ j ] a [ k + 1 ] )
f [ i 1 ] [ k ] + a [ k ] f [ i 1 ] [ k ] a [ k + 1 ] j 无关,可以预处理。

代码:

#include<algorithm>
#include<iostream>
#include<cstring>
#include<cstdio>
#define fo(i, j, k) for (int i = j; i <= k; i++)
#define fw(i, j, k) for (int i = j; i >= k; i--)
#define inf 0x7fffffff
#define N 3005

using namespace std;

int f[N][N], g[N][N], a[N], n, r;

void Work(int x, int y) {
    if (x != 0) Work(x - 1, g[x][y]);
    printf("%d ", y + 1);
}

int main() { 
    scanf("%d %d", &n, &r);
    fo(i, 0, n-1) scanf("%d", &a[i]);
    fo(i, 1, n) 
       fo(j, 0, n-2) f[i][j] = -inf;
    fo(i, 1, n) {
         int ans = -inf, num;
         fo(j, 0, n-2) {
              if (ans < f[i-1][j] + a[((j - (i-1) * r) % n + n) % n]) {
                  ans = f[i-1][j] + a[((j - (i-1) * r) % n + n) % n];
                  num = j;
              }
              if (f[i][j] < ans - a[((j - (i-1) * r + 1) % n + n) % n]) {
                  f[i][j] = ans - a[((j - (i-1) * r + 1) % n + n) % n];
                  g[i][j] = num;
              }
         }
         ans = -inf;
         fw(j, n-2, 0) {
              if (ans < f[i-1][j] - a[((j - (i-1) * r + 1) % n + n) % n]) {
                  ans = f[i-1][j] - a[((j  -(i-1) * r + 1) % n + n) % n];
                  num = j;
              }
              if (f[i][j] < ans + a[((j - (i-1) * r) % n + n) % n]) {
                  f[i][j] = ans + a[((j - (i-1) * r) % n + n) % n];
                  g[i][j] = num;
              }     
         }
    }
    int ans = -inf, num;
    fo(i, 0, n-2)
         if (ans < f[n][i]) 
             ans = f[n][i], num = i;
    printf("%d\n",ans);
    Work(n, num);
}

猜你喜欢

转载自blog.csdn.net/gx_man_vip/article/details/81007373
今日推荐