• [LOJ2288][THUWC2017]大葱的神力:搜索+背包DP+费用流+随机化


    分析

    测试点1、2:搜索+剪枝。

    测试点3:只有一个抽屉,直接01背包。

    测试点4、5:每个物品体积相同,说明每个抽屉能放下的物品个数固定,建图跑费用流。

    测试点6:每个物品体积相近,经过验证发现每个抽屉能放下的物品个数仍然固定,费用流。

    测试点7:除了第一个物品,其他物品体积相同。所以可以枚举第一个物品放在哪个抽屉,然后费用流。

    测试点8、9、10:随机化贪心,如果不是人品爆发基本不可能过(博主没过)。

    代码

    测试点3

    #include <iostream>
    #include <cstdio>
    #include <cstdlib>
    #include <cstring>
    #include <cmath>
    #include <cctype>
    #include <algorithm>
    #define rin(i,a,b) for(int i=(a);i<=(b);i++)
    #define rec(i,a,b) for(int i=(a);i>=(b);i--)
    #define trav(i,a) for(int i=head[(a)];i;i=e[i].nxt)
    typedef long long LL;
    using std::cin;
    using std::cout;
    using std::endl;
    
    inline int read(){
    	int x;scanf("%d",&x);return x;
    }
    
    const int MAXN=2005;
    const int MAXS=10005;
    int n,m,s,v[MAXN],w[MAXN];
    int f[MAXN][MAXS],pre[MAXN][MAXS];
    int ans[MAXN];
    
    int main(){
    	freopen("drawer3.in","r",stdin);
    	freopen("drawer3.out","w",stdout);
    	n=read(),m=read();
    	rin(i,1,n) v[i]=read();
    	s=read();
    	rin(i,1,n) w[i]=read();
    	rin(i,1,n) rec(j,s,v[i]){
    		f[i][j]=f[i-1][j];
    		pre[i][j]=j;
    		if(f[i-1][j-v[i]]+w[i]>f[i][j]){
    			f[i][j]=f[i-1][j-v[i]]+w[i];
    			pre[i][j]=j-v[i];
    		}
    	}
    	int now=s,pos=n;
    	while(pos){
    		if(pre[pos][now]<now) ans[pos]=1;
    		now=pre[pos][now];
    		pos--;
    	}
    	rin(i,1,n) printf("%d ",ans[i]);
    	printf("
    ");
    	return 0;
    }
    

    测试点4、5、6

    #include <iostream>
    #include <cstdio>
    #include <cstdlib>
    #include <cstring>
    #include <cmath>
    #include <cctype>
    #include <algorithm>
    #include <queue>
    #define rin(i,a,b) for(int i=(a);i<=(b);i++)
    #define rec(i,a,b) for(int i=(a);i>=(b);i--)
    #define trav(i,a) for(int i=head[(a)];i;i=e[i].nxt)
    typedef long long LL;
    using std::cin;
    using std::cout;
    using std::endl;
    
    inline int read(){
    	int x;scanf("%d",&x);return x;
    }
    
    const int MAXN=1005;
    const int MAXM=205;
    int n,m,S,T,mincost,v,c[MAXM],w[MAXN][MAXM],ecnt=1,head[MAXN+MAXM];
    int dis[MAXN+MAXM],pre[MAXN+MAXM];
    bool book[MAXN+MAXM];
    std::queue<int> q;
    struct Edge{
    	int to,nxt,cap,ost;
    }e[(MAXN+MAXM+MAXN*MAXM)<<1];
    
    inline void add_edge(int bg,int ed,int cap,int ost){
    	ecnt++;
    	e[ecnt].to=ed;
    	e[ecnt].nxt=head[bg];
    	e[ecnt].cap=cap;
    	e[ecnt].ost=ost;
    	head[bg]=ecnt;
    }
    
    inline bool spfa(){
    	memset(dis,0x3f,sizeof dis);
    	while(!q.empty()) q.pop();
    	dis[S]=0;
    	q.push(S);
    	book[S]=1;
    	while(!q.empty()){
    		int x=q.front();q.pop();
    		trav(i,x){
    			int ver=e[i].to;
    			if(dis[ver]>dis[x]+e[i].ost&&e[i].cap){
    				dis[ver]=dis[x]+e[i].ost;
    				pre[ver]=i;
    				if(!book[ver]){
    					q.push(ver);
    					book[ver]=1;
    				}
    			}
    		}
    		book[x]=0;
    	}
    	return dis[T]<1e9;
    }
    
    inline void upd(){
    	int now=T,flow=1e9;
    	while(now!=S){
    		flow=std::min(flow,e[pre[now]].cap);
    		now=e[pre[now]^1].to;
    	}
    	now=T;
    	while(now!=S){
    		e[pre[now]].cap-=flow;
    		e[pre[now]^1].cap+=flow;
    		now=e[pre[now]^1].to;
    	}
    	mincost+=flow*dis[T];
    }
    
    inline void ek(){
    	while(spfa()) upd();
    }
    
    int main(){
    	freopen("drawer6.in","r",stdin);
    	freopen("drawer6.out","w",stdout);
    	n=read(),m=read();
    	S=n+m+1,T=S+1;
    	rin(i,1,n){
    		v=read();
    		add_edge(S,i,1,0);
    		add_edge(i,S,0,0);
    	}
    	rin(i,1,m){
    		c[i]=read()/v;
    		add_edge(n+i,T,c[i],0);
    		add_edge(T,n+i,0,0);
    	}
    	rin(i,1,n) rin(j,1,m){
    		w[i][j]=read();
    		add_edge(i,n+j,1,-w[i][j]);
    		add_edge(n+j,i,0,w[i][j]);
    	}
    	ek();
    	rin(i,1,n){
    		bool flag=0;
    		trav(j,i){
    			int ver=e[j].to;
    			if(ver==S) continue;
    			if(!e[j].cap){
    				printf("%d ",ver-n);
    				flag=1;break;
    			}
    		}
    		if(!flag) printf("0 ");
    	}
    	printf("
    ");
    	return 0;
    }
    

    测试点7

    #include <iostream>
    #include <cstdio>
    #include <cstdlib>
    #include <cstring>
    #include <cmath>
    #include <cctype>
    #include <algorithm>
    #include <queue>
    #define rin(i,a,b) for(int i=(a);i<=(b);i++)
    #define rec(i,a,b) for(int i=(a);i>=(b);i--)
    #define trav(i,a) for(int i=head[(a)];i;i=e[i].nxt)
    typedef long long LL;
    using std::cin;
    using std::cout;
    using std::endl;
    
    inline int read(){
    	int x;scanf("%d",&x);return x;
    }
    
    const int MAXN=1005;
    const int MAXM=205;
    int n,m,S,T,mincost,v,c[MAXM],w[MAXN][MAXM],ecnt=1,head[MAXN+MAXM];
    int dis[MAXN+MAXM],pre[MAXN+MAXM];
    bool book[MAXN+MAXM];
    std::queue<int> q;
    struct Edge{
    	int to,nxt,cap,ost;
    }e[(MAXN+MAXM+MAXN*MAXM)<<1];
    
    inline void add_edge(int bg,int ed,int cap,int ost){
    	ecnt++;
    	e[ecnt].to=ed;
    	e[ecnt].nxt=head[bg];
    	e[ecnt].cap=cap;
    	e[ecnt].ost=ost;
    	head[bg]=ecnt;
    }
    
    inline bool spfa(){
    	memset(dis,0x3f,sizeof dis);
    	while(!q.empty()) q.pop();
    	dis[S]=0;
    	q.push(S);
    	book[S]=1;
    	while(!q.empty()){
    		int x=q.front();q.pop();
    		trav(i,x){
    			int ver=e[i].to;
    			if(dis[ver]>dis[x]+e[i].ost&&e[i].cap){
    				dis[ver]=dis[x]+e[i].ost;
    				pre[ver]=i;
    				if(!book[ver]){
    					q.push(ver);
    					book[ver]=1;
    				}
    			}
    		}
    		book[x]=0;
    	}
    	return dis[T]<1e9;
    }
    
    inline void upd(){
    	int now=T,flow=1e9;
    	while(now!=S){
    		flow=std::min(flow,e[pre[now]].cap);
    		now=e[pre[now]^1].to;
    	}
    	now=T;
    	while(now!=S){
    		e[pre[now]].cap-=flow;
    		e[pre[now]^1].cap+=flow;
    		now=e[pre[now]^1].to;
    	}
    	mincost+=flow*dis[T];
    }
    
    inline void ek(){
    	while(spfa()) upd();
    }
    
    int main(){
    	freopen("drawer7.in","r",stdin);
    	freopen("drawer7.out","w",stdout);
    	n=read(),m=read();
    	S=n+m+1,T=S+1;
    	int v1=read();
    	rin(i,2,n){
    		v=read();
    	}
    	rin(i,1,m){
    		c[i]=read();
    	}
    	rin(i,1,n) rin(j,1,m){
    		w[i][j]=read();
    	}
    	int minpos=-1,umincost=0;
    	rin(k,1,m){
    		ecnt=1,mincost=0;
    		memset(head,0,sizeof head);
    		c[k]-=v1;
    		mincost-=w[1][k];
    		rin(i,2,n){
    			add_edge(S,i,1,0);
    			add_edge(i,S,0,0);
    		}
    		rin(i,1,m){
    			add_edge(n+i,T,c[i]/v,0);
    			add_edge(T,n+i,0,0);
    		}
    		rin(i,2,n) rin(j,1,m){
    			add_edge(i,n+j,1,-w[i][j]);
    			add_edge(n+j,i,0,w[i][j]);
    		}
    		ek();
    		if(mincost<umincost){
    			umincost=mincost;
    			minpos=k;
    		}
    		c[k]+=v1;
    	}
    	ecnt=1,mincost=0;
    	memset(head,0,sizeof head);
    	rin(i,2,n){
    		add_edge(S,i,1,0);
    		add_edge(i,S,0,0);
    	}
    	rin(i,1,m){
    		add_edge(n+i,T,c[i]/v,0);
    		add_edge(T,n+i,0,0);
    	}
    	rin(i,2,n) rin(j,1,m){
    		add_edge(i,n+j,1,-w[i][j]);
    		add_edge(n+j,i,0,w[i][j]);
    	}
    	ek();
    	if(mincost<umincost){
    		umincost=mincost;
    		minpos=0;
    	}
    	else{
    		int k=minpos;
    		ecnt=1,mincost=0;
    		memset(head,0,sizeof head);
    		c[k]-=v1;
    		mincost-=w[1][k];
    		rin(i,2,n){
    			add_edge(S,i,1,0);
    			add_edge(i,S,0,0);
    		}
    		rin(i,1,m){
    			add_edge(n+i,T,c[i]/v,0);
    			add_edge(T,n+i,0,0);
    		}
    		rin(i,2,n) rin(j,1,m){
    			add_edge(i,n+j,1,-w[i][j]);
    			add_edge(n+j,i,0,w[i][j]);
    		}
    		ek();
    	}
    	printf("%d ",minpos);
    	rin(i,2,n){
    		bool flag=0;
    		trav(j,i){
    			int ver=e[j].to;
    			if(ver==S) continue;
    			if(!e[j].cap){
    				printf("%d ",ver-n);
    				flag=1;break;
    			}
    		}
    		if(!flag) printf("0 ");
    	}
    	printf("
    ");
    	return 0;
    }
    

    测试点8、9、10

    #include <iostream>
    #include <cstdio>
    #include <cstdlib>
    #include <cstring>
    #include <cmath>
    #include <cctype>
    #include <algorithm>
    #include <ctime>
    #include <vector>
    #define rin(i,a,b) for(int i=(a);i<=(b);i++)
    #define rec(i,a,b) for(int i=(a);i>=(b);i--)
    #define trav(i,a) for(int i=head[(a)];i;i=e[i].nxt)
    typedef long long LL;
    using std::cin;
    using std::cout;
    using std::endl;
    
    inline int read(){
    	int x;scanf("%d",&x);return x;
    }
    
    const int MAXN=1005;
    const int MAXM=305;
    int n,m,v[MAXN],c[MAXM],blg[MAXN];
    bool vis[MAXN];
    std::vector<int> vec[MAXM],maxvec[MAXM];
    struct Pair{
    	int id,w;
    	inline friend bool operator < (Pair A,Pair B){
    		return 1.0*A.w/v[A.id]>1.0*B.w/v[B.id];
    	}
    }a[MAXM][MAXN];
    
    inline int work(){
    	memset(vis,0,sizeof vis);
    	int ret=0;
    	rin(i,1,m){
    		vec[i].clear();
    		int rem=c[i];
    		rin(j,1,n){
    			if(vis[a[i][j].id]||rem<v[a[i][j].id]) continue;
    			if((rand()%(n*2))>n+vec[i].size()) continue;
    			vec[i].push_back(a[i][j].id);
    			vis[a[i][j].id]=1;
    			rem-=v[a[i][j].id];
    			ret+=a[i][j].w;
    		}
    	}
    	return ret;
    }
    
    int main(){
    	freopen("drawer10.in","r",stdin);
    	freopen("drawer10.out","w",stdout);
    	srand(time(0));
    	n=read(),m=read();
    	rin(i,1,n) v[i]=read();
    	rin(i,1,m) c[i]=read();
    	rin(i,1,n) rin(j,1,m) a[j][i]=(Pair){i,read()};
    	rin(i,1,m) std::sort(a[i]+1,a[i]+n+1);
    	int maxans=0;
    	rin(k,1,10000){
    		int temp=work();
    		if(temp>maxans){
    			memset(blg,0,sizeof blg);
    			rin(i,1,m) rin(j,0,(int)vec[i].size()-1)
    				blg[vec[i][j]]=i;
    			maxans=temp;
    		}
    	}
    	rin(i,1,n) printf("%d ",blg[i]);
    	printf("
    ");
    	return 0;
    }
    
  • 相关阅读:
    插入排序
    dojo树的节点添加链接的例子
    Discuz 3x 配置问题
    mysql_connect() 不支持 请检查 mysql 模块是否正确加载
    IIS访问php页面问题,报告404错误
    Map使用操作系统内存的情况
    IT级别
    java类型和mysql类型的转换
    C++析构函数的自动调用问题
    c++中虚函数
  • 原文地址:https://www.cnblogs.com/ErkkiErkko/p/10182925.html
Copyright © 2020-2023  润新知