zoukankan      html  css  js  c++  java
  • 分数规划

    切了三道01分数规划的题目,特来总结;

    [分数规划]老司机飙车

    大致题意是求最小比率生成树;

    经过数学变形化为二分的最小生成树问题;

    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #include<cmath>
    #include<algorithm>
    #include<ctime>
    #include<cstdlib>
    #include<iomanip>
    using namespace std;
    #define LL long long
    #define up(i,j,n) for(int i=(j);i<=(n);i++)
    #define FILE "dealing"
    const int maxn=1010,inf=10;
    const double eps=0.0005;
    int n;
    int x[maxn],y[maxn],z[maxn];
    double d[maxn][maxn],Dan[maxn][maxn];
    int read(){
    	int x=0,f=1,ch=getchar();
    	while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
    	while(ch>='0'&&ch<='9'){x=(x<<1)+(x<<3)+ch-'0';ch=getchar();}
    	return f*x;
    }
    struct node{
    	int x,y;
    	double v;
    	bool operator<(const node& b)const{return v<b.v;}
    }e[maxn*maxn];
    int len=0;
    int fa[maxn];
    int getfa(int x){return fa[x]==x?x:fa[x]=getfa(fa[x]);}
    bool Kruskal(){
    	int fx,fy;
    	double sum=0;
    	up(i,1,n)fa[i]=i;
    	sort(e+1,e+len+1);
    	up(i,1,len){
    		fx=getfa(e[i].x);
    		fy=getfa(e[i].y);
    		if(fx!=fy)fa[fx]=fy,sum+=e[i].v;
    	}
    	if(sum<0)return 1;
    	return 0;
    }
    int squ(int x){return x*x;}
    int main(){
    	n=read();
    	up(i,1,n)x[i]=read(),y[i]=read(),z[i]=read();
    	up(i,1,n)up(j,i+1,n){
    		Dan[i][j]=sqrt(1.0*squ(x[i]-x[j])+squ(y[i]-y[j]));
    		d[i][j]=abs(z[i]-z[j]);
    	}
    	double left=0,right=inf;
    	while(right-left>=eps){
    		double mid=(left+right)/2;
    		len=0;
    		up(i,1,n)up(j,i+1,n)e[++len].x=i,e[len].y=j,e[len].v=d[i][j]-mid*Dan[i][j];
    		if(Kruskal())right=mid;
    		else left=mid;
    	}
    	printf("%.3lf
    ",left);
    	return 0;
    }
    

     [分数规划]必须切断与文化课的连接

    大致意思是求最小密度割(使割的总权值除以割边的数目最小)

    二分后,构造新图,负权边直接选中,正权边进行最小割,加起来,验证是否可行;

    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #include<ctime>
    #include<cstdlib>
    #include<cmath>
    #include<algorithm>
    #include<iomanip>
    using namespace std;
    #define LL long long
    #define up(i,j,n) for(int i=(j);i<=(n);i++)
    #define FILE "dealing"
    int read(){
    	int f=1,x=0,ch=getchar();
    	while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
    	while(ch>='0'&&ch<='9')x=(x<<1)+(x<<3)+ch-'0',ch=getchar();
    	return f*x;
    }
    const int maxn=2010,inf=100000000;
    const double eps=0.001; 
    int n,m,s,t;
    struct node{
    	int y,next,rev;
    	double flow;
    }e[maxn];
    int linkk[maxn],len=0;
    int x[maxn],y[maxn];
    double v[maxn];
    bool cmp(double x,double y){return abs(x-y)<=eps;}
    void insert(int x,int y,double flow){
    	e[++len].y=y;
    	e[len].flow=flow;
    	e[len].rev=len+1;
    	e[len].next=linkk[x];
    	linkk[x]=len;
    	e[++len].y=x;
    	e[len].flow=0;
    	e[len].next=linkk[y];
    	linkk[y]=len;
    	e[len].rev=len-1;
    }
    int q[maxn],tail=0,head=0,d[maxn];
    bool makelevel(){
    	tail=head=0;
    	memset(d,10,sizeof(d));
    	q[++tail]=s;int x;
    	d[s]=0;
    	while(++head<=tail){
    		x=q[head];
    		for(int i=linkk[x];i;i=e[i].next)
    			if(d[e[i].y]>inf&&!cmp(e[i].flow,0))d[e[i].y]=d[x]+1,q[++tail]=e[i].y;
    	}
    	return d[t]<inf;
    }
    double makeflow(int x,double flow){
    	if(x==t)return flow;
    	double dis,maxflow=0;
    	for(int i=linkk[x];i&&maxflow<flow&&!cmp(maxflow,flow);i=e[i].next){
    		if(!cmp(e[i].flow,0)&&d[e[i].y]==d[x]+1)
    			if(dis=makeflow(e[i].y,min(flow-maxflow,e[i].flow))){
    				maxflow+=dis;
    				e[i].flow-=dis;
    				e[e[i].rev].flow+=dis;
    			}
    	}
    	if(maxflow<=eps&&maxflow>=eps)d[x]=-1;
    	return maxflow;
    }
    double dinic(){
    	double d,ans=0;
    	while(makelevel())
    		while(d=makeflow(s,inf))
    			ans+=d;
    	return ans;
    }
    int que[maxn],cnt=0,vis[maxn],w[maxn],Cnt=0;
    void dfs(int o){
    	vis[o]=1;
    	for(int i=linkk[o];i;i=e[i].next)
    		if(!vis[e[i].y]&&!cmp(e[i].flow,0))dfs(e[i].y);
    }
    int main(){
    	n=read(),m=read();s=1,t=n;
    	up(i,1,m)x[i]=read(),y[i]=read(),v[i]=read();
    	double left=0,right=inf;
    	while(right-left>=eps){
    		double mid=(left+right)/2,sum=0;
    		len=0;
    		memset(linkk,0,sizeof(linkk));
    		up(i,1,m){
    			if(v[i]-mid<=0)sum+=(v[i]-mid);
    			else insert(x[i],y[i],v[i]-mid),insert(y[i],x[i],v[i]-mid);
    		}
    		sum+=dinic();
    		if(sum<=0)right=mid;
    		else left=mid;
    	}
    	up(i,1,m)if(v[i]-left<0)que[++cnt]=i;
    	dfs(s);
    	up(i,1,n)if(!vis[i])
    		up(j,1,m)if((x[j]==i&&vis[y[j]])||(y[j]==i&&vis[x[j]]))que[++cnt]=j;
    	sort(que+1,que+cnt+1);
    	up(i,1,cnt)
    		if(que[i]!=que[i-1])w[++Cnt]=que[i];
    	printf("%d
    ",Cnt);
    	up(i,1,Cnt)printf("%d
    ",w[i]);
    	return 0;
    }
    

     [分数规划]炉石传说校队(为什么都是些奇奇怪怪的名字?)

    大致题意是求最大密度子图;

    详见胡伯涛论文;

    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #include<ctime>
    #include<cstdlib>
    #include<cmath>
    #include<algorithm>
    #include<iomanip>
    using namespace std;
    #define LL long long
    #define up(i,j,n) for(int i=(j);i<=(n);i++)
    #define FILE "dealing"
    int read(){
    	int f=1,x=0,ch=getchar();
    	while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
    	while(ch>='0'&&ch<='9')x=(x<<1)+(x<<3)+ch-'0',ch=getchar();
    	return f*x;
    }
    const int maxn=2010,inf=100000000;
    const double eps=0.001; 
    int n,m,s,t;
    struct node{
    	int y,next,rev;
    	double flow;
    }e[maxn];
    int linkk[maxn],len=0;
    int x[maxn],y[maxn];
    double v[maxn];
    bool cmp(double x,double y){return abs(x-y)<=eps;}
    void insert(int x,int y,double flow){
    	e[++len].y=y;
    	e[len].flow=flow;
    	e[len].rev=len+1;
    	e[len].next=linkk[x];
    	linkk[x]=len;
    	e[++len].y=x;
    	e[len].flow=0;
    	e[len].next=linkk[y];
    	linkk[y]=len;
    	e[len].rev=len-1;
    }
    int q[maxn],tail=0,head=0,d[maxn];
    bool makelevel(){
    	tail=head=0;
    	memset(d,10,sizeof(d));
    	q[++tail]=s;int x;
    	d[s]=0;
    	while(++head<=tail){
    		x=q[head];
    		for(int i=linkk[x];i;i=e[i].next)
    			if(d[e[i].y]>inf&&!cmp(e[i].flow,0))d[e[i].y]=d[x]+1,q[++tail]=e[i].y;
    	}
    	return d[t]<inf;
    }
    double makeflow(int x,double flow){
    	if(x==t)return flow;
    	double dis,maxflow=0;
    	for(int i=linkk[x];i&&maxflow<flow&&!cmp(maxflow,flow);i=e[i].next){
    		if(!cmp(e[i].flow,0)&&d[e[i].y]==d[x]+1)
    			if(dis=makeflow(e[i].y,min(flow-maxflow,e[i].flow))){
    				maxflow+=dis;
    				e[i].flow-=dis;
    				e[e[i].rev].flow+=dis;
    			}
    	}
    	if(maxflow<=eps&&maxflow>=eps)d[x]=-1;
    	return maxflow;
    }
    double dinic(){
    	double d,ans=0;
    	while(makelevel())
    		while(d=makeflow(s,inf))
    			ans+=d;
    	return ans;
    }
    int que[maxn],cnt=0,vis[maxn],w[maxn],Cnt=0;
    void dfs(int o){
    	vis[o]=1;
    	for(int i=linkk[o];i;i=e[i].next)
    		if(!vis[e[i].y]&&!cmp(e[i].flow,0))dfs(e[i].y);
    }
    int main(){
    	n=read(),m=read();s=1,t=n;
    	up(i,1,m)x[i]=read(),y[i]=read(),v[i]=read();
    	double left=0,right=inf;
    	while(right-left>=eps){
    		double mid=(left+right)/2,sum=0;
    		len=0;
    		memset(linkk,0,sizeof(linkk));
    		up(i,1,m){
    			if(v[i]-mid<=0)sum+=(v[i]-mid);
    			else insert(x[i],y[i],v[i]-mid),insert(y[i],x[i],v[i]-mid);
    		}
    		sum+=dinic();
    		if(sum<=0)right=mid;
    		else left=mid;
    	}
    	up(i,1,m)if(v[i]-left<0)que[++cnt]=i;
    	dfs(s);
    	up(i,1,n)if(!vis[i])
    		up(j,1,m)if((x[j]==i&&vis[y[j]])||(y[j]==i&&vis[x[j]]))que[++cnt]=j;
    	sort(que+1,que+cnt+1);
    	up(i,1,cnt)
    		if(que[i]!=que[i-1])w[++Cnt]=que[i];
    	printf("%d
    ",Cnt);
    	up(i,1,Cnt)printf("%d
    ",w[i]);
    	return 0;
    }
  • 相关阅读:
    DataGridView重绘painting简单实例
    C#实现万年历(农历、节气、节日、星座、属相、生肖、闰年等)
    《开源框架那点事儿11》:软件开发杂谈
    半年总结——欲戴王冠,必承其重
    三天学会HTML5 之第一天
    读书笔记 -《高效程序猿的45个习惯-敏捷开发修炼之道》
    Opengl ES 1.x NDK实例开发之七:旋转的纹理立方体
    我与小娜(08):人工智能的伟大胜利
    阿里云 oss 小文件上传进度显示
    模仿猫眼电影App一个动画效果
  • 原文地址:https://www.cnblogs.com/chadinblog/p/6288377.html
Copyright © 2011-2022 走看看