题意
给定一个由2行n列组成的矩阵,矩阵的行从上到下编号为1到2,列从左到右编号为1到n。矩阵中的每个单元格 (i, j) 包含一个整数,初始时单元格 (i, j) 中的整数为 $a_{i,j}$ 。
可以进行任意次数的列交换操作(包括0次):选择两列x和y(1 ≤ x < y ≤ n),然后交换第一行的 $a_{1,x}$ 与 $a_{1,y}$ ,以及第二行的 $a_{2,x}$ 与 $a_{2,y}$ 。
操作完成后,需要从单元格(1, 1)选择一条路径到单元格(2, n)。路径上的每个单元格(i, j)(除了最后一个)的下一个单元格可以是(i + 1, j)或(i, j + 1)。路径不能超出矩阵边界。
路径的成本是路径上所有(n + 1)个单元格中的整数之和。目标是通过执行操作和选择路径,使得路径的成本尽可能大。
题解
在所有n*2个格子中,需要绕开 $n-1$ 个格子,使用贪心,肯定是绕开数值最小的格子。
又因为不可能同时绕开处在一列的两个格子,故此处需要维护。
CODE
#include<iostream> #include<algorithm> using namespace std; const int N = 5000 + 10;
  struct Cell{     int value, column; }a[N * 2];
  bool cmp(Cell a, Cell b){     return a.value < b.value; } void resolution(){     int n, sum = 0;     bool flg[N];     cin >> n;     for(int i = 1; i <= n * 2; i++){         cin >> a[i].value;         a[i].column = (i % n != 0 ? i%n : n);         sum += a[i].value;         flg[a[i].column] = 1;     }     sort(a + 1, a + n*2 + 1, cmp);     int cnt = n - 1, t = 1;     while(cnt){         if(flg[a[t].column]){             flg[a[t].column] = 0;             sum -= a[t].value;             t++;             cnt--;                      }else{             t++;         }     }     cout << sum << endl;     return ; }
  int main(){     ios::sync_with_stdio(0);     int T;     cin >> T;     while(T--){         resolution();     }     return 0; }
   |