题目

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. 11月13日上午ajax返回数据类型为JSON数据的处理

    ajax返回数据类型为JSON数据的处理 <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" &qu ...

  2. 清北学堂模拟赛day7 错排问题

    /* 考虑一下已经放回m本书的情况,已经有书的格子不要管他,考虑没有书的格子,不考虑错排有(n-m)!种,在逐步考虑有放回原来位置的情况,已经放出去和已经被占好的格子,不用考虑,剩下全都考虑,设t=x ...

  3. linux下共享库的注意点之-fpic

    在编译共享库必须加上-fpic.这是为什么呢? 首先看一个简单的例子: #include <stdio.h> int fun1() { printf("fun1\n") ...

  4. [Data Structure & Algorithm] 八大排序算法

    排序有内部排序和外部排序之分,内部排序是数据记录在内存中进行排序,而外部排序是因排序的数据很大,一次不能容纳全部的排序记录,在排序过程中需要访问外存.我们这里说的八大排序算法均为内部排序. 下图为排序 ...

  5. eclipse version

    查看Eclipse的版本号: 1. 找到eclipse安装目录 2. 进入readme文件夹,打开readme_eclipse.html 3. readme_eclipse.html呈现的第二行即数字 ...

  6. Solr5.4.0部署到Tomcat

    所用工具 下载 solr 5.4.0 版本:http://www.apache.org/dyn/closer.lua/lucene/solr/5.4.0 下载 Tomcat(6以上版本),另外可以根据 ...

  7. CSS实现多个Div等高,类似表格布局

    <%@ taglib prefix="tiles" uri="http://tiles.apache.org/tags-tiles"%> <% ...

  8. iOS开发——高级篇——iOS中常见的设计模式(MVC/单例/委托/观察者)

    关于设计模式这个问题,在网上也找过一些资料,下面是我自己总结的,分享给大家 如果你刚接触设计模式,我们有好消息告诉你!首先,多亏了Cocoa的构建方式,你已经使用了许多的设计模式以及被鼓励的最佳实践. ...

  9. cain使用教程

    Cain & Abel 是由Oxid.it开发的一个针对Microsoft操作系统的免费口令恢复工具.号称穷人使用的L0phtcrack.它的功能十分强大,可以网络嗅探,网络欺骗,破解加密口令 ...

  10. getComputedStyle的简单用法

    var number=window.getComputedStyle("元素").style样式名