zoukankan      html  css  js  c++  java
  • 【[六省联考2017]寿司餐厅】

    题目

    发现数据范围非常小就可以猜想这是一个网络流

    又发现权值有正有负,就可以猜想这是一个最大权闭合子图

    选择一个区间([i,j])就必须要选择其所有子区间,这也非常符合最大权闭合子图的模型

    但是我们枚举([i,j])像所有子区间连边显然并不是非常可取,因为这样会建出(O(n^4))级别的边来

    所以实际上我们只需要让([i,j])([i+1,j])([i,j-1])连容量为(inf)边就可以了,这样一直连下去就相当于对所有的子区间连边了

    常规操作还有权值为正就由(S)连,权值为负就去连(T)

    之后我们对于编号为(x)的寿司我们开一个点,向汇点连(mx^2)的边,每个种类为(x)的单点向汇点再连(x)的边就好了

    代码

    #include<algorithm>
    #include<iostream>
    #include<cstring>
    #include<cstdio>
    #include<queue>
    #define re register
    #define maxn 6005
    #define LL long long
    #define inf 999999999
    #define max(a,b) ((a)>(b)?(a):(b))
    #define min(a,b) ((a)<(b)?(a):(b))
    inline int read()
    {
    	char c=getchar();int x=0,r=1;
    	while(c<'0'||c>'9') {if(c=='-') r=-1;c=getchar();}
    	while(c>='0'&&c<='9') x=(x<<3)+(x<<1)+c-48,c=getchar();return r*x;
    }
    struct E{int v,nxt,w,f;}e[2000005];
    int S,T,n,m,num=1,tot,cnt,ans;
    int d[maxn],cur[maxn],head[maxn];
    int a[105],b[105],val[105][105],w[105],to[105][105];
    inline void add_edge(int x,int y,int z) {e[++num].v=y;e[num].nxt=head[x];head[x]=num;e[num].w=z;}
    inline void add(int x,int y,int z) {add_edge(x,y,z),add_edge(y,x,0);}
    inline int BFS()
    {
    	std::queue<int> q;
    	for(re int i=S;i<=T;i++) d[i]=0,cur[i]=head[i];
    	q.push(S);d[S]=1;
    	while(!q.empty())
    	{
    		int k=q.front();q.pop();
    		for(re int i=head[k];i;i=e[i].nxt)
    		if(!d[e[i].v]&&e[i].w>e[i].f) d[e[i].v]=d[k]+1,q.push(e[i].v);
    	}
    	return d[T];
    } 
    int dfs(int x,int now)
    {
        if(x==T||!now) return now;
        int flow=0,ff;
        for(re int& i=cur[x];i;i=e[i].nxt)
        if(d[x]+1==d[e[i].v])
        {
            ff=dfs(e[i].v,min(e[i].w-e[i].f,now));
            if(ff<=0) continue;
            now-=ff,flow+=ff;
            e[i].f+=ff,e[i^1].f-=ff;
            if(!now) break;
        }
        return flow;
    }
    inline int find(int x) 
    {
    	int l=1,r=tot;
    	while(l<=r) {int mid=l+r>>1;if(b[mid]==x) return mid;if(b[mid]>x) r=mid-1;else l=mid+1;}
    	return 0;
    }
    int main()
    {
    	n=read(),m=read();
    	for(re int i=1;i<=n;i++) w[i]=b[i]=a[i]=read();
    	std::sort(b+1,b+n+1);tot=std::unique(b+1,b+n+1)-b-1;
    	for(re int i=1;i<=n;i++) a[i]=find(a[i]);
    	for(re int i=1;i<=n;i++)
    		for(re int j=1;j<=n-i+1;j++)
    			{val[i][i+j-1]=read(),to[i][i+j-1]=++cnt;if(val[i][i+j-1]>0) ans+=val[i][i+j-1];}
    	T=cnt+tot+1;
    	for(re int i=1;i<=n;i++)
    		for(re int j=1;j<=n-i+1;j++)
    			if(val[i][i+j-1]>0) add(S,to[i][i+j-1],val[i][i+j-1]);
    				else add(to[i][i+j-1],T,-1*val[i][i+j-1]);
    	for(re int i=1;i<=n;i++)
    		for(re int j=1;j<=n-i+1;j++)
    			if(i!=i+j-1) 
    			{
    				add(to[i][i+j-1],to[i+1][i+j-1],inf);
    				if(j>1) add(to[i][i+j-1],to[i][i+j-2],inf);
    			}
    			else add(to[i][i+j-1],T,w[i]),add(to[i][i+j-1],a[i]+cnt,inf);
    	for(re int i=1;i<=tot;i++) add(i+cnt,T,b[i]*b[i]*m);
    	while(BFS()) 
    		ans-=dfs(S,inf);
    	printf("%d
    ",ans);
    	return 0;
    }
    
    
  • 相关阅读:
    每日一篇文献:Robotic pick-and-place of novel objects in clutter with multi-affordance grasping and cross-domain image matching
    每日一篇文献:Intuitive Bare-Hand Teleoperation of a Robotic Manipulator Using Virtual Reality and Leap Motion
    每日一篇文献:Virtual Kinesthetic Teaching for Bimanual Telemanipulation
    HEBI Robotic Arm VR Teleoperation
    「iQuotient Case」AR device teleoperated robotic arm
    VR and Digital Twin Based Teleoperation of Robotic Arm
    HEBI Robotic Arm VR Teleoperation
    Human Robot Interaction
    Immersive Teleoperation Project
    机器人演示学习
  • 原文地址:https://www.cnblogs.com/asuldb/p/10300632.html
Copyright © 2011-2022 走看看