题目传送门:http://codeforces.com/problemset/problem/1038/E

题意:给出$N$个方块,每个方块有左右两种颜色$a,b$(可以翻转使左右两种颜色交换)和一个权值$w$。当某个方块的右侧颜色与另一个方块的左侧颜色相同,它们可以连成一个大块,一个大块可以由若干个小块像这样连成(一个大块中可以只包含一个小块)。定义大块的权值为组成它的所有小块的权值和,问可以连成的大块中最大的权值。$N \leq 100 , a , b \leq 4 , w \leq 10^5$


看到$a,b \leq 4$就是神题预定

方法一:搜索

将四种颜色看做点,方块是连接左右两种颜色的边,就可以得到一个边为$100$,点为$4$的图,目标是找到一个边权和最大的简单路。然后我们可以发现图上很多的边是没有意义的。比如:

①某个方块左右两侧同色(在图上表示自环),这样子的边权直接算作点权即可。

②很多方块左右颜色相同(在图上表示重边),因为这些过多的重边可以通过在两个端点不断绕环,所以在搜索的时候经过它们很多次是没有必要的,所以考虑根据奇偶性将边数大于$3$的重边压成边数为$3$或者$2$(考试的时候想的是$2$或$1$但是考虑边为奇数的也有可能最后丢掉一条边到另外的颜色,所以必须留下$2$或$3$条),其中$2$或$1$条为原来最短边和次短边/最短边,而剩下的一条边则为其他重边压成的边,边权为它们的和。

经过这两种处理,图上的边的数量变为了最多$18$条,搜索可以承受(而且跑得贼快)。

 #include<bits/stdc++.h>
 using namespace std;

 vector < ][];
 ] , cnt[][] , N , ans;

 bool cmp(int a , int b){
     return a > b;
 }

 void dfs(int now , int cnt){
     int k = pri[now];
     cnt += pri[now];
     pri[now] = ;
      ; i <=  ; i++)
         if(!Edge[now][i].empty()){
             ];
             Edge[now][i].erase(Edge[now][i].begin());
             Edge[i][now].erase(Edge[i][now].begin());
             dfs(i , cnt + t);
             Edge[now][i].insert(Edge[now][i].begin() , t);
             Edge[i][now].insert(Edge[i][now].begin() , t);
         }
     ans = max(ans , cnt);
     pri[now] += k;
 }

 int main(){
     cin >> N;
      ; i <= N ; i++){
         int a , b , c;
         cin >> a >> b >> c;
         swap(b , c);
         if(a == b)
             pri[a] += c;
         else{
             Edge[a][b].push_back(c);
             Edge[b][a].push_back(c);
             cnt[a][b]++;
             cnt[b][a]++;
         }
     }
      ; i <=  ; i++)
          ; j <=  ; j++){
             sort(Edge[i][j].begin() , Edge[i][j].end() , cmp);
             )
                 ){
                      , p = Edge[i][j][cnt[i][j] - ] , q = Edge[i][j][cnt[i][j] - ];
                      ; k < cnt[i][j] -  ; k++)
                         sum += Edge[i][j][k];
                     Edge[i][j].clear();
                     Edge[i][j].push_back(sum);
                     Edge[i][j].push_back(p);
                     Edge[i][j].push_back(q);
                 }
                 else{
                      , p = Edge[i][j][cnt[i][j] -];
                      ; k < cnt[i][j] -  ; k++)
                         sum += Edge[i][j][k];
                     Edge[i][j].clear();
                     Edge[i][j].push_back(sum);
                     Edge[i][j].push_back(p);
                 }
         }
      ; i <=  ; i++)
         dfs(i , );
     cout << ans;
     ;
 }

方法二:DP

设$f_{i,j,k,l}$表示选择$i$到$j$段的方块,大块左端颜色为$k$,右端颜色为$r$的时候获得的最大权值,考虑转移:

①由其中两段拼接而成:$f_{i,p,k,q}+f_{p+1,j,q,l}$

②由其中两段换位拼接而成(因为本身方块的拼接是无序的):$f_{i,p,q,l}+f_{p+1,j,k,q}$

③只取左边一部分或者右边一部分:$f_{i,p,k,l}$或$f_{p,j,k,l}$

注意非法转移情况要用极小值覆盖,所以才有③转移才会产生最优值的情况。

 #include<bits/stdc++.h>
 using namespace std;

 ][][][] , l[] , r[] , w[];

 int main(){
     int N;
     cin >> N;
      ; i <= N ; i++)
         cin >> l[i] >> w[i] >> r[i];
     memset(dp , -0x3f , sizeof(dp));
      ; i <= N ; i++)
         dp[i][i][l[i]][r[i]] = dp[i][i][r[i]][l[i]] = w[i];
      ; i ; i--)
          ; j <= N ; j++)
              ; p <=  ; p++)
                  ; q <=  ; q++)
                     for(int k = i ; k < j ; k++){
                         dp[i][j][p][q] = max(dp[i][j][p][q] , max(dp[i][k][p][q] , dp[k + ][j][p][q]));
                          ; l <=  ; l++)
                             dp[i][j][p][q] = max(dp[i][j][p][q] , max(dp[i][k][p][l] + dp[k + ][j][l][q] , dp[i][k][l][q] + dp[k + ][j][p][l]));
                     }
     ;
      ; i <=  ; i++)
          ; j <=  ; j++)
             all = max(all , dp[][N][i][j]);
     cout << all;
     ;
 }

CF1038E Maximum Matching 搜索/区间DP的更多相关文章

  1. lightoj 1283 - Shelving Books(记忆化搜索+区间dp)

    题目链接:http://www.lightoj.com/volume_showproblem.php?problem=1283 题解:这题很显然一看就像是区间dp,但是单纯的区间dp好像解决不了问题可 ...

  2. 洛谷P1514 引水入城 [搜索,区间DP]

    题目传送门 引水入城 题目描述 在一个遥远的国度,一侧是风景秀美的湖泊,另一侧则是漫无边际的沙漠.该国的行政区划十分特殊,刚好构成一个 N 行×M 列的矩形,如上图所示,其中每个格子都代表一座城市,每 ...

  3. poj1179 区间dp(记忆化搜索写法)有巨坑!

    http://poj.org/problem?id=1179 Description Polygon is a game for one player that starts on a polygon ...

  4. UVA 10003 Cutting Sticks 区间DP+记忆化搜索

    UVA 10003 Cutting Sticks+区间DP 纵有疾风起 题目大意 有一个长为L的木棍,木棍中间有n个切点.每次切割的费用为当前木棍的长度.求切割木棍的最小费用 输入输出 第一行是木棍的 ...

  5. HDU 4597 Play Game(区间DP(记忆化搜索))

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=4597 题目大意: 有两行卡片,每个卡片都有各自的权值. 两个人轮流取卡片,每次只能从任一行的左端或右端 ...

  6. CF149D. Coloring Brackets[区间DP !]

    题意:给括号匹配涂色,红色蓝色或不涂,要求见原题,求方案数 区间DP 用栈先处理匹配 f[i][j][0/1/2][0/1/2]表示i到ji涂色和j涂色的方案数 l和r匹配的话,转移到(l+1,r-1 ...

  7. BZOJ1055: [HAOI2008]玩具取名[区间DP]

    1055: [HAOI2008]玩具取名 Time Limit: 10 Sec  Memory Limit: 162 MBSubmit: 1588  Solved: 925[Submit][Statu ...

  8. HDU 4293---Groups(区间DP)

    题目链接 http://acm.split.hdu.edu.cn/showproblem.php?pid=4293 Problem Description After the regional con ...

  9. Light OJ 1031---Easy Game(区间DP)

    题目链接 http://lightoj.com/volume_showproblem.php?problem=1031 Description You are playing a two player ...

随机推荐

  1. 方差variance, 协方差covariance, 协方差矩阵covariance matrix

    https://www.jianshu.com/p/e1c8270477bc?utm_campaign=maleskine&utm_content=note&utm_medium=se ...

  2. 使用node.js进行API自动化回归测试

    概述 传统的QA自动化测试通常是基于GUI的,比如使用Selenium,模拟用户在界面上操作.但GUI测试的开发.维护成本和运行的稳定性一直是测试界的老大难问题.投入大量的人力物力开发.维护.运行,却 ...

  3. Tsung 超详细的的tsung性能测试资料

    超详细的的tsung性能测试资料 by:授客 QQ:1033553122 由于篇幅问题,采用链接分享的形式 下载连接:理解Tsung配置文件 下载连接:基准测试方法 下载连接:Tsung XML配置文 ...

  4. Java:【面向对象:抽象类,接口】

    本文内容: 抽象类 接口 抽象类与接口的异同 首发日期:2018-03-24 抽象类: 虽然已经有了父类,但有时候父类也是无法直接描述某些共有属性的,比如哺乳类和人类都会叫,而一般来说哺乳类这个父类并 ...

  5. [20171113]修改表结构删除列相关问题2.txt

    [20171113]修改表结构删除列相关问题2.txt --//测试看看修改表结构删除列产生的redo向量,对这些操作细节不了解,分析redo看看. 1.环境:SCOTT@book> @ &am ...

  6. 12-openldap使用AD密码

    阅读视图 本文严重参考 Openldap 整合windows AD认证 本文其他参考 OpenLDAP使用AD密码 Configuring OpenLDAP pass-through authenti ...

  7. 用LinQ扩展方法,泛型扩展方法,实现自定义验证字符是否空、对象是否为null,及泛型约束使用,Action的使用

    一.Linq扩展方法 1.扩展方法必须是静态方法.扩展方法所在的类必须是静态类 2.扩展方法里面的参数必须制定this关键字,紧跟需要扩展的类型,如下: 二.泛型约束 1.使用泛型的原因,是在不知道需 ...

  8. VMware虚拟机中CentOS 7的硬盘空间扩容

    查看centos7系统挂载点信息 扩展VMWare-centos7硬盘空间 对新增加的硬盘进行分区.格式化 添加新LVM到已有的LVM组,实现扩容 1.查看centos7系统挂载点信息 df -h查看 ...

  9. GUI_键盘事件

    import java.awt.Button; import java.awt.FlowLayout; import java.awt.Frame; import java.awt.TextField ...

  10. 【SDOI2009】Bill的挑战

    Description Sheng bill不仅有惊人的心算能力,还可以轻松地完成各种统计.在昨天的比赛中,你凭借优秀的程序与他打成了平局,这导致Sheng bill极度的不满.于是他再次挑战你.这次 ...