HDU5900 QSC and Master(区间DP + 最小费用最大流)
题目
Source
http://acm.hdu.edu.cn/showproblem.php?pid=5900
Description
Every school has some legends, Northeastern University is the same.
Enter from the north gate of Northeastern University,You are facing the main building of Northeastern University.Ninety-nine percent of the students have not been there,It is said that there is a monster in it.
QSCI am a curious NEU_ACMer,This is the story he told us.
It’s a certain period,QSCI am in a dark night, secretly sneaked into the East Building,hope to see the master.After a serious search,He finally saw the little master in a dark corner. The master said:
“You and I, we're interfacing.please solve my little puzzle!
There are N pairs of numbers,Each pair consists of a key and a value,Now you need to move out some of the pairs to get the score.You can move out two continuous pairs,if and only if their keys are non coprime(their gcd is not one).The final score you get is the sum of all pair’s value which be moved out. May I ask how many points you can get the most?
The answer you give is directly related to your final exam results~The young man~”
QSC is very sad when he told the story,He failed his linear algebra that year because he didn't work out the puzzle.
Could you solve this puzzle?
(Data range:1<=N<=300
1<=Ai.key<=1,000,000,000
0<Ai.value<=1,000,000,000)
Input
First line contains a integer T,means there are T(1≤T≤10) test case。
Each test case start with one integer N . Next line contains N integers,means Ai.key.Next line contains N integers,means Ai.value.
Output
For each test case,output the max score you could get in a line.
Sample Input
3
3
1 2 3
1 1 1
3
1 2 4
1 1 1
4
1 3 4 3
1 1 1 1
Sample Output
0
2
0
分析
题目大概说给N个<key,value>二元组,每次可以取出相邻的且其key的GCD不为1的两个二元组,并获得二者value之和的价值,问能取到的最大价值是多少?
注意取掉后就左右两部分就合并在一起。。
显然考虑区间DP:
- dp[i][j]表示下标i到j的二元组全部消除能获得的最大价值
- 通过枚举k(i<=k<j)从max(dp[i][k]+dp[k+1][j])转移;此外如果key[i]等于key[j],还能从dp[i+1][j-1]+value[i]+value[j]转移
于是这样就能求出所有能消除的全部区间以及消除它们能获得的最大价值,而问题就是要从这些区间取出不重叠的几个使得价值和最大。
这个可以用最小费用最大流解,区间k覆盖。。也能再dp一次,dp[i]表示考虑坐标点在i之前的区间所能获得的最大价值。。
代码
#include<cstdio>
#include<cstring>
#include<queue>
#include<algorithm>
using namespace std;
#define INF (1LL<<60)
#define MAXN 333
#define MAXM 3333*666
struct Edge{
int u,v,next;
long long cap,cost;
}edge[MAXM];
int head[MAXN];
int NV,NE,vs,vt; void addEdge(int u,int v,long long cap,long long cost){
edge[NE].u=u; edge[NE].v=v; edge[NE].cap=cap; edge[NE].cost=cost;
edge[NE].next=head[u]; head[u]=NE++;
edge[NE].u=v; edge[NE].v=u; edge[NE].cap=0; edge[NE].cost=-cost;
edge[NE].next=head[v]; head[v]=NE++;
}
bool vis[MAXN];
long long dis[MAXN];
int pre[MAXN];
bool SPFA(){
for(int i=0; i<NV; ++i){
vis[i]=0;
dis[i]=INF;
}
vis[vs]=1;
dis[vs]=0;
queue<int> que;
que.push(vs);
while(!que.empty()){
int u=que.front(); que.pop();
for(int i=head[u]; i!=-1; i=edge[i].next){
int v=edge[i].v;
if(edge[i].cap && dis[v]>dis[u]+edge[i].cost){
dis[v]=dis[u]+edge[i].cost;
pre[v]=i;
if(!vis[v]){
vis[v]=1;
que.push(v);
}
}
}
vis[u]=0;
}
return dis[vt]!=INF;
}
long long MCMF(){
long long res=0;
while(SPFA()){
long long flow=INF,cost=0;
for(int u=vt; u!=vs; u=edge[pre[u]].u){
flow=min(flow,edge[pre[u]].cap);
}
for(int u=vt; u!=vs; u=edge[pre[u]].u){
edge[pre[u]].cap-=flow;
edge[pre[u]^1].cap+=flow;
cost+=flow*edge[pre[u]].cost;
}
res+=cost;
}
return res;
} long long d[MAXN][MAXN]; long long gcd(long long a,long long b){
if(b==0) return a;
return gcd(b,a%b);
} bool ok[MAXN][MAXN]; long long key[MAXN],val[MAXN]; int main(){
int t,n;
scanf("%d",&t);
while(t--){
scanf("%d",&n);
for(int i=1; i<=n; ++i){
scanf("%I64d",key+i);
}
for(int i=1; i<=n; ++i){
scanf("%I64d",val+i);
}
memset(ok,0,sizeof(ok));
for(int i=1; i<=n; ++i){
for(int j=i+1; j<=n; ++j){
if(gcd(key[i],key[j])==1) continue;
ok[i][j]=1;
ok[j][i]=1;
}
}
for(int i=1; i<=n; ++i){
for(int j=1; j<=n; ++j){
d[i][j]=-INF;
}
}
for(int len=2; len<=n; ++len){
for(int i=1; i+len-1<=n; ++i){
if(ok[i][i+len-1] && len==2){
d[i][i+len-1]=val[i]+val[i+len-1];
continue;
}
if(ok[i][i+len-1]) d[i][i+len-1]=max(d[i][i+len-1],val[i]+val[i+len-1]+d[i+1][i+len-1-1]);
for(int j=0; j<len-1; ++j){
d[i][i+len-1]=max(d[i][i+len-1],d[i][i+j]+d[i+j+1][i+len-1]);
}
}
}
long long ans=0; vs=0; vt=n+2; NV=vt+1; NE=0;
memset(head,-1,sizeof(head));
addEdge(vs,1,1,0);
addEdge(n+1,vt,1,0);
for(int i=1; i<=n; ++i){
addEdge(i,i+1,INF,0);
}
for(int i=1; i<=n; ++i){
for(int j=i+1; j<=n; ++j){
if(d[i][j]!=-INF){
addEdge(i,j+1,1,-d[i][j]);
}
}
}
printf("%I64d\n",-MCMF());
}
}
HDU5900 QSC and Master(区间DP + 最小费用最大流)的更多相关文章
- 2016 年沈阳网络赛---QSC and Master(区间DP)
题目链接 http://acm.hdu.edu.cn/showproblem.php?pid=5900 Problem Description Every school has some legend ...
- HDU 5900 QSC and Master 区间DP
QSC and Master Problem Description Every school has some legends, Northeastern University is the s ...
- hdu4106 区间k覆盖问题(连续m个数,最多选k个数) 最小费用最大流 建图巧妙
/** 题目:hdu4106 区间k覆盖问题(连续m个数,最多选k个数) 最小费用最大流 建图巧妙 链接:http://acm.hdu.edu.cn/showproblem.php?pid=4106 ...
- poj3680 Intervals 区间k覆盖问题 最小费用最大流 建图巧妙
/** 题目:poj3680 Intervals 区间k覆盖问题 最小费用最大流 建图巧妙 链接:http://poj.org/problem?id=3680 题意:给定n个区间,每个区间(ai,bi ...
- 51Nod 1084 矩阵取数问题 V2 —— 最小费用最大流 or 多线程DP
题目链接:http://www.51nod.com/onlineJudge/questionCode.html#!problemId=1084 1084 矩阵取数问题 V2 基准时间限制:2 秒 空 ...
- ZOJ3762 The Bonus Salary!(最小费用最大流)
题意:给你N个的任务一定要在每天的[Li,Ri]时段完成,然后你只有K天的时间,每个任务有个val,然后求K天里能够获得的最大bonus. 思路:拿到手第一直觉是最小费用最大流,然后不会建图,就跑去想 ...
- hdu 2686 Matrix 最小费用最大流
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=2686 Yifenfei very like play a number game in the n*n ...
- HDU - 6437 Problem L.Videos 2018 Multi-University Training Contest 10 (最小费用最大流)
题意:M个影片,其属性有开始时间S,结束时间T,类型op和权值val.有K个人,每个人可以看若干个时间不相交的影片,其获得的收益是这个影片的权值val,但如果观看的影片相邻为相同的属性,那么收益要减少 ...
- BZOJ 1221: [HNOI2001] 软件开发【最小费用最大流】
Description 某软件公司正在规划一项n天的软件开发计划,根据开发计划第i天需要ni个软件开发人员,为了提高软件开发人员的效率,公司给软件人员提供了很多的服务,其中一项服务就是要为每个开发人员 ...
随机推荐
- 在Windows Server 2008中布置Web站点时遇到的问题及解决办法
首先安装了VS2012. 首先在计算机--管理 中添加服务器角色, 添加角色: 进行各种设置: 选择对应的应用程序池,原来默认的是: 需要添加一个4.0的. 添加后,原因:在安装Framework v ...
- 【09-23】js原型继承学习笔记
js原型继承学习笔记 function funcA(){ this.a="prototype a"; } var b=new funcA(); b.a="object a ...
- postgresql利用pg_upgrade升级数据库(从8.4升级到9.5)
其他见:http://my.oschina.net/ensn/blog/636766 本文利用pg_upgrade实现将8.4.18版本升级到9.5.0版本,8.4.18版本为RedHat系统自带pg ...
- 利用session_set_save_handler()函数将session保存到MySQL数据库中
PHP保存session默认的是采用的文件的方式来保存的,这仅仅在文件的空间开销很小的windows上是可以采用的,但是如果我们采用uinx或者是liux上的文件系统的时候,这样的文件系统的文件空间开 ...
- vue2.0学习(二)
1.关于模板渲染,当需要渲染多个元素时可以 <ul> <template v-for="item in items"> <li>{{ item. ...
- WDCP突破phpmyadmin导入文件时只有20M
WDCP在默认的配置下,PHPMYADMIN的上传上限是20M,很多时候我们的数据库大小已经大于了20M了,那这时候改怎么办呢?下面就用简单的话,告诉大家如何解决这一个问题.方法: 登录到WDCP的后 ...
- window共享linux下的文件 samba
1.在Ubuntu上安装samba服务 sudo apt-get install samba 2.修改配置文件vim /etc/samba/smb.conf [xubu] (共享名) guest ac ...
- single-table inheritance 单表继承
type 字段在 Rails 中默认使用来做 STI(single-table inheritance),当 type 作为普通字段来使用时,可以把SIT的列设置成别的列名(比如不存在的某个列). 文 ...
- python __call__ 内置函数的使用
对象通过提供__call__(slef, [,*args [,**kwargs]])方法可以模拟函数的行为, 如果一个对象x提供了该方法,就可以像函数一样使用它,也就是说x(arg1, arg2... ...
- Python基础四
1. 集合 主要作用: 去重 关系测试, 交集\差集\并集\反向(对称)差集 2. 元组 只读列表,只有count, index 2 个方法 作用:如果一些数据不想被人修改, 可以存成元组,比如身 ...