• 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
    ",-MCMF());
    	}
    }
    
  • 相关阅读:
    Lakehouse: 统一数据仓库和高级分析的新一代开放平台
    mac进入恢复模式,关闭/启动系统完整性(SIP)
    多个xcode版本并存,切换xcode版本
    pod执行指定缓存目录,多版本pod执行缓存目录被清问题
    java特殊处理String.format中的%,使用%做一次转义
    html div设置占屏幕占比高度(使用vh)
    vue+leaflet 地图相关
    vue 集成天地图
    vue iframe嵌套外部网页
    Fabric.js
  • 原文地址:https://www.cnblogs.com/WABoss/p/5883182.html
Copyright © 2020-2023  润新知