CF#508 1038E Maximum Matching

~~~题面~~~

题解:

  感觉还是比较妙的,复杂度看上去很高(其实也很高),但是因为n只有100,所以还是可以过的。

  考虑一个很暴力的状态f[i][j][x][y]表示考虑取区间i ~ j的方格,左右端点颜色分别是x, y.的最大值。

  那么有如下转移

  1,直接继承子区间的答案

    f[i][j][x][y] = max(f[i][k][x][y], f[k + 1][j][x][y]);//因为子区间就这2种,毕竟子区间一定比当前区间小,因此不靠在端点上的区间一定已经被靠在端点上的区间给取过max了。

  2,由2段子区间拼凑而来,相当于枚举中间断开的地方是选了那个块.//如果中间断开的地方的块没有被选,那么一定可以找到一个被选的块作为断点(如果找不到就说明这整个区间内只取了端点,再转移也没有什么意义。)

    翻转操作是不需要考虑的,因为可以在初始化的地方就处理掉,因此只需要在转移的地方考虑一下乱序继承即可。

    即正常的顺序是[i, l] + [l + 1, j] = [i, j];

    乱序则可以支持[l + 1][j] + [i, l] = [i, j];

    所以对于这2种情况都转移一下,转移的时候必须要求相接的地方颜色相同即可。

  注意因为有子区间相加转移的地方,所以初始化为极小值的时候不要太小了,不然太小了直接一加就爆了。

 1 #include<bits/stdc++.h>
 2 using namespace std;
 3 #define R register int
 4 #define AC 110
 5 #define ac 6
 6 
 7 int n, ans;
 8 int f[AC][AC][ac][ac];
 9 
10 inline int read()
11 {
12     int x = 0;char c = getchar();
13     while(c > '9' || c < '0') c = getchar();
14     while(c >= '0' && c <= '9') x = x * 10 + c - '0', c = getchar();
15     return x;
16 }
17 
18 void pre()
19 {
20     n = read();
21     memset(f, -63, sizeof(f));
22     int a, b, c;
23     for(R i = 1; i <= n; i ++)
24     {
25         a = read(), b = read(), c = read();
26         f[i][i][a][c] = f[i][i][c][a] = b;
27     }
28 }
29 
30 inline void upmax(int &a, int b)
31 {
32     if(b > a) a = b;
33 }
34 
35 void work()
36 {
37     for(R i = n; i; i --)
38         for(R j = i; j <= n; j ++)
39             for(R x = 1; x <= 4; x ++)
40                 for(R y = 1; y <= 4; y ++)
41                 {
42                     for(R l = i; l < j; l ++)
43                     {
44                         upmax(f[i][j][x][y], max(f[i][l][x][y], f[l + 1][j][x][y]));
45                         for(R k = 1; k <= 4; k ++)
46                         {
47                             upmax(f[i][j][x][y], f[i][l][x][k] + f[l + 1][j][k][y]);
48                             upmax(f[i][j][x][y], f[i][l][k][y] + f[l + 1][j][x][k]);
49                         }
50                     }
51                     upmax(ans, f[i][j][x][y]);
52                 }
53     printf("%d
", ans);
54 }
55 
56 int main()
57 {
58     //freopen("in.in", "r", stdin);
59     pre();
60     work();
61     //fclose(stdin);
62     return 0;
63 }
View Code
原文地址:https://www.cnblogs.com/ww3113306/p/9840159.html