题目

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 + 最小费用最大流)的更多相关文章

  1. 2016 年沈阳网络赛---QSC and Master(区间DP)

    题目链接 http://acm.hdu.edu.cn/showproblem.php?pid=5900 Problem Description Every school has some legend ...

  2. HDU 5900 QSC and Master 区间DP

    QSC and Master Problem Description   Every school has some legends, Northeastern University is the s ...

  3. hdu4106 区间k覆盖问题(连续m个数,最多选k个数) 最小费用最大流 建图巧妙

    /** 题目:hdu4106 区间k覆盖问题(连续m个数,最多选k个数) 最小费用最大流 建图巧妙 链接:http://acm.hdu.edu.cn/showproblem.php?pid=4106 ...

  4. poj3680 Intervals 区间k覆盖问题 最小费用最大流 建图巧妙

    /** 题目:poj3680 Intervals 区间k覆盖问题 最小费用最大流 建图巧妙 链接:http://poj.org/problem?id=3680 题意:给定n个区间,每个区间(ai,bi ...

  5. 51Nod 1084 矩阵取数问题 V2 —— 最小费用最大流 or 多线程DP

    题目链接:http://www.51nod.com/onlineJudge/questionCode.html#!problemId=1084 1084 矩阵取数问题 V2  基准时间限制:2 秒 空 ...

  6. ZOJ3762 The Bonus Salary!(最小费用最大流)

    题意:给你N个的任务一定要在每天的[Li,Ri]时段完成,然后你只有K天的时间,每个任务有个val,然后求K天里能够获得的最大bonus. 思路:拿到手第一直觉是最小费用最大流,然后不会建图,就跑去想 ...

  7. hdu 2686 Matrix 最小费用最大流

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=2686 Yifenfei very like play a number game in the n*n ...

  8. HDU - 6437 Problem L.Videos 2018 Multi-University Training Contest 10 (最小费用最大流)

    题意:M个影片,其属性有开始时间S,结束时间T,类型op和权值val.有K个人,每个人可以看若干个时间不相交的影片,其获得的收益是这个影片的权值val,但如果观看的影片相邻为相同的属性,那么收益要减少 ...

  9. BZOJ 1221: [HNOI2001] 软件开发【最小费用最大流】

    Description 某软件公司正在规划一项n天的软件开发计划,根据开发计划第i天需要ni个软件开发人员,为了提高软件开发人员的效率,公司给软件人员提供了很多的服务,其中一项服务就是要为每个开发人员 ...

随机推荐

  1. String类的功能

    String类              标红的为较少出现的 1.判断功能 boolean equals(Object obj) :比较字符串内容是否相同,区分大小写 boolean equalsIg ...

  2. Python Day6

    面向对象 概述 面向过程:根据业务逻辑从上到下写垒代码 函数式:将某功能代码封装到函数中,日后便无需重复编写,仅调用函数即可 面向对象:对函数进行分类和封装,让开发"更快更好更强...&qu ...

  3. Bootstrap学习笔记

    Bootstrap提供了一套响应式.移动设备优先的流式栅格系统. Bootstrap把一个容器或整个网页平均分成了12列. 栅格系统必须放在.container或container-fluid中 样式 ...

  4. C语言基础(1)-基本语法及注意事项

    1. include 头文件包含 #include <stdio.h>这个是hello world程序的第一句话 # 代表预编译指令 #include的意思就是头文件包含,使用C语言库函数 ...

  5. 前端工具之Gulp

    Gulp是一款前端自动化的工具,如果能熟练使用Gulp来进行开发一定可以节省很多的时间,也可以快速的提高工作效率. 在使用Gulp之前就是要配置好Gulp安装的环境,这是我们能使用Gulp快速开发的第 ...

  6. redirect()重新定向·

  7. 解决Xftp经常断开连接的问题,Xftp中文乱码

    #文件 --> 选项 --> 勾选“发送保持活动状态消息” 间隔 60秒 #工具 -> 选项 延伸阅读: Xshell个性化设置,解决Xshell遇到中文显示乱码的问题

  8. PHP函数call_user_func和call_user_func_array详解

    今天在群里面,有个叫lewis的在问call_user_func_array的用法,因为之前一直没有用过,也不能说什么,于是看一下手册,发现是这么写的: call_user_func_array (P ...

  9. MySQL数据类型 int(M) 表示什么意思?详解mysql int类型的长度值问题

    MySQL 数据类型中的 integer types 有点奇怪.你可能会见到诸如:int(3).int(4).int(8) 之类的 int 数据类型.刚接触 MySQL 的时候,我还以为 int(3) ...

  10. edghasdz

    匹配2016年10月8日19时51分50秒匹配 可以使用