CF1038E Maximum Matching 搜索/区间DP
题目传送门: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的更多相关文章
- lightoj 1283 - Shelving Books(记忆化搜索+区间dp)
题目链接:http://www.lightoj.com/volume_showproblem.php?problem=1283 题解:这题很显然一看就像是区间dp,但是单纯的区间dp好像解决不了问题可 ...
- 洛谷P1514 引水入城 [搜索,区间DP]
题目传送门 引水入城 题目描述 在一个遥远的国度,一侧是风景秀美的湖泊,另一侧则是漫无边际的沙漠.该国的行政区划十分特殊,刚好构成一个 N 行×M 列的矩形,如上图所示,其中每个格子都代表一座城市,每 ...
- poj1179 区间dp(记忆化搜索写法)有巨坑!
http://poj.org/problem?id=1179 Description Polygon is a game for one player that starts on a polygon ...
- UVA 10003 Cutting Sticks 区间DP+记忆化搜索
UVA 10003 Cutting Sticks+区间DP 纵有疾风起 题目大意 有一个长为L的木棍,木棍中间有n个切点.每次切割的费用为当前木棍的长度.求切割木棍的最小费用 输入输出 第一行是木棍的 ...
- HDU 4597 Play Game(区间DP(记忆化搜索))
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=4597 题目大意: 有两行卡片,每个卡片都有各自的权值. 两个人轮流取卡片,每次只能从任一行的左端或右端 ...
- CF149D. Coloring Brackets[区间DP !]
题意:给括号匹配涂色,红色蓝色或不涂,要求见原题,求方案数 区间DP 用栈先处理匹配 f[i][j][0/1/2][0/1/2]表示i到ji涂色和j涂色的方案数 l和r匹配的话,转移到(l+1,r-1 ...
- BZOJ1055: [HAOI2008]玩具取名[区间DP]
1055: [HAOI2008]玩具取名 Time Limit: 10 Sec Memory Limit: 162 MBSubmit: 1588 Solved: 925[Submit][Statu ...
- HDU 4293---Groups(区间DP)
题目链接 http://acm.split.hdu.edu.cn/showproblem.php?pid=4293 Problem Description After the regional con ...
- Light OJ 1031---Easy Game(区间DP)
题目链接 http://lightoj.com/volume_showproblem.php?problem=1031 Description You are playing a two player ...
随机推荐
- docker 部署 java 项目
Docker Docker官方网址: https://docs.docker.com/ 英文地址 Docker中文网址: http://www.docker.org.cn/ 中文地址 Docker是 ...
- javascript arguments参数问题
function f(a, b, c){ alert(arguments.length); // result: "2" a = 100; alert(arguments[0]); ...
- 开始记录 Windows Phone 生涯
已经快接近三年没有更新博客了,最近打算把博客这块从新建设起来. 由于工作原因,现在已经很久没有接触过Android了.目前工作是全力 Windows Phone,并且也已经工作一年半了,以后会陆续把之 ...
- 配置Synwrite作为Python的IDE
先建立批处理 建立SynPython.bat ::Synwrite call Python to compile file ::Set Path @ set PATH=H:\XPprogram\Cod ...
- Kotlin入门(13)类成员的众生相
上一篇文章介绍了类的简单定义及其构造方式,当时为了方便观察演示结果,在示例代码的构造函数中直接调用toast提示方法,但实际开发是不能这么干的.合理的做法是外部访问类的成员属性或者成员方法,从而获得处 ...
- JMeter—配置元件(七)
参考<全栈性能测试修炼宝典JMeter实战>第六章 JMeter 元件详解中第二节配置元件JMeter配置元件可以用来初始化默认值和变量,以便后续采样器使用.将在其作用域的初始化阶段处理. ...
- 线程:生命周期、实现方式、start()和run()的区别!
1.线程的生命周期 要想实现多线程,必须在主线程中创建新的线程对象.Java语言使用Thread类及其子类的对象来表示线程,在它的 一个完整的生命周期中通常要经历如下的五种状态: 新建:当一个Thre ...
- Python用户名密码登录系统(MD5加密并存入文件,三次输入错误将被锁定)及对字符串进行凯撒密码加解密操作
# -*- coding: gb2312 -*- #用户名密码登录系统(MD5加密并存入文件)及对字符串进行凯撒密码加解密操作 #作者:凯鲁嘎吉 - 博客园 http://www.cnblogs.co ...
- Beta冲刺(1/5)(麻瓜制造者)
今天小组进行了第一次冲刺,虽然新组员还没有确定. 今日完成任务 邓弘立:修改登录代码 李佳铭: 用户收藏UI代码编写 江郑: 进行了后台管理员界面ui的设计和环境的搭建 刘双玉:后台github仓库建 ...
- Activiti工作流与BPMN2.0规范
本章内容根据BPMN2.0规范的分类划分为以下部分: 1.启动与结束事件(event) 2.顺序流(Sequence Flow) 3.任务(Task) 4.网关(Gateway) 5.子流程(Subp ...