• [CLYZ2017]day4


    猜测

    image

    soulution

    100分

    \(x,y\)坐标可以建二分图.
    因为求的是所有合法猜测猜对的个数的最小值,所以考虑最小费用最大流.
    \(s\)\(x_i\)连一条容量为\(x_i\)出现次数,费用为\(0\)的有向边;
    \(y_i\)\(t\)连一条容量为\(y_i\)出现次数,费用为\(0\)的有向边;
    \((x_i,y_i)\)为特殊格子,从\(x_i\)\(y_i\)连一条容量为\(1\),费用为\(1\)的有向边;否则,从\(x_i\)\(y_i\)连一条容量为\(1\),费用为\(0\)的有向边.

    #include<cmath>
    #include<ctime>
    #include<queue>
    #include<stack>
    #include<cstdio>
    #include<vector>
    #include<cstring>
    #include<cstdlib>
    #include<iostream>
    #include<algorithm>
    #define N 105
    #define M 10005
    #define K 100005
    using namespace std;
    struct graph{
    	int nxt,to,f,w;
    }e[M];
    struct point{
    	int e,v;
    }pre[N];
    bool inq[N];queue<int> q;
    int x[N],y[N],px[K],py[K],tx[K],ty[K];
    int b[N][N],g[N],dis[N],n,m,s,t,cnt=1,tot;
    inline void addedge(int x,int y,int f,int w){
        e[++cnt].nxt=g[x];g[x]=cnt;
        e[cnt].to=y;e[cnt].f=f;e[cnt].w=w;
    }
    inline void adde(int x,int y,int f,int w){
    	addedge(x,y,f,w);addedge(y,x,0,-w);
    }
    inline bool spfa(int u){
        for(int i=1;i<=t;++i)
            dis[i]=M;
        q.push(u);dis[u]=0;inq[u]=true;
        while(!q.empty()){
            u=q.front();q.pop();inq[u]=false;
            for(int i=g[u];i;i=e[i].nxt)
                if(e[i].f>0&&dis[u]+e[i].w<dis[e[i].to]){
                    dis[e[i].to]=dis[u]+e[i].w;
                    pre[e[i].to].e=i;pre[e[i].to].v=u;
                    if(!inq[e[i].to]){
                        q.push(e[i].to);inq[e[i].to]=true;
                    } 
                } 
        }
        return dis[t]<M;
    }
    inline int mf(){
    	int ret=0,d;
    	while(spfa(s)){
    		d=n;
    		for(int i=t;i!=s;i=pre[i].v)
    			d=min(d,e[pre[i].e].f);
    		ret+=d*dis[t];
    		for(int i=t;i!=s;i=pre[i].v){
    			e[pre[i].e].f-=d;
    			e[pre[i].e^1].f+=d;
    		}
    	}
    	return ret;
    }
    inline void Aireen(){
    	scanf("%d",&n);
    	for(int i=1;i<=n;++i){
    		scanf("%d%d",&x[i],&y[i]);
    		++tx[x[i]];++ty[y[i]];
    	}
    	for(int i=1;i<K;++i)
    		if(tx[i]) px[i]=++tot;
    	m=tot;
    	for(int i=1;i<K;++i)
    		if(ty[i]) py[i]=++tot;
    	s=tot+1;t=s+1;
    	
    	for(int i=1;i<K;++i)
    		if(tx[i]) adde(s,px[i],tx[i],0);
    	for(int i=1;i<K;++i)
    		if(ty[i]) adde(py[i],t,ty[i],0);
    	for(int i=1;i<=n;++i)
    		b[px[x[i]]][py[y[i]]]=1;
    	for(int i=1;i<=m;++i)
    		for(int j=m+1;j<=tot;++j)
    			adde(i,j,1,b[i][j]);
    	printf("%d\n",mf());
    }
    int main(){
    	freopen("guess.in","r",stdin);
    	freopen("guess.out","w",stdout);
    	Aireen();
    	fclose(stdin);
    	fclose(stdout);
    	return 0;
    }
    

    开房间

    image

    60分

    \(f[i][j][k](j<k)\)表示第\(i\)关,\(A\)\(j\),\(B\)\(k\)的最小消耗.
    \(f[i][j][k]=min\{f[i-1][l][q]+|j-l|+|k-q|\}+t_{i,l}+t_{i,q}(j<k,l<q)\)
    \(ans=min\{f[n][j][k]\}(j<k)\).

    100分

    类似完全背包那样优化.
    \(f[i][j][k]=min\{f[i-1][j][k],f[i][j-1][k],f[i][j+1][k],f[i][j][k-1],f[i][j][k+1]\}\).
    通过注意枚举顺序,还可以把\(i\)那一维压掉.

    #include<cmath>
    #include<ctime>
    #include<queue>
    #include<stack>
    #include<cstdio>
    #include<vector>
    #include<cstring>
    #include<cstdlib>
    #include<iostream>
    #include<algorithm>
    #define N 305
    #define INF 600000000
    using namespace std;
    int f[N][N],t[N][N],n,m,k,ans;
    inline int min(int x,int y){
    	return x<y?x:y;
    }
    inline void Aireen(){
    	scanf("%d%d%d",&n,&m,&k); 
    	for(int i=1;i<=n;++i)
    		for(int j=1;j<=m;++j)
    			scanf("%d",&t[i][j]);
    	for(int i=0;i<=m+1;++i)
    		for(int j=0;j<=m+1;++j)
    			f[i][j]=INF;
    	for(int j=1;j<=m;++j)
    		for(int l=j+1;l<=m;++l)
    			f[j][l]=t[1][j]+t[1][l];
    	for(int i=2;i<=n;++i){
    		for(int j=1;j<=m;++j)
    			for(int l=j+1;l<=m;++l)
    				f[j][l]=min(f[j][l],min(f[j-1][l],f[j][l-1])+k);
    		for(int j=m;j;--j)
    			for(int l=m;l>j;--l)
    				f[j][l]=min(f[j][l],min(f[j+1][l],f[j][l+1])+k);
    		for(int j=1;j<=m;++j)
    			for(int l=j+1;l<=m;++l)
    				f[j][l]+=t[i][j]+t[i][l];
    	}
    	ans=INF;
    	for(int i=1;i<=m;++i)
    		for(int j=i+1;j<=m;++j)
    			ans=min(ans,f[i][j]);
    	printf("%d\n",ans);
    }
    int main(){
    	freopen("room.in","r",stdin);
    	freopen("room.out","w",stdout);
    	Aireen();
    	fclose(stdin);
    	fclose(stdout);
    	return 0;
    }
    
  • 相关阅读:
    Comprehend-Elasticsearch-Demo5
    Mxnet使用TensorRT加速模型--Mxnet官方例子
    Mxnet模型转换ONNX,再用tensorrt执行前向运算
    MxNet模型转换Onnx
    基于Flask-APScheduler实现添加动态定时任务
    Golang习题
    算法题
    Celery使用指南
    flask拓展(数据库操作)
    flask进阶(上下文源管理源码浅析)
  • 原文地址:https://www.cnblogs.com/AireenYe/p/CLYZ2017day4.html
Copyright © 2020-2023  润新知