zoukankan      html  css  js  c++  java
  • [HDU6094]Rikka with KMatch

    CXXXIII.[HDU6094]Rikka with K-Match

    依旧wqs二分。

    首先,依据我们之前提到过的一个性质,“凡是可以表示成费用流模型的东西都有凹凸性”,本题也不例外,关于匹配个数的函数是凹的。

    凹的就可以wqs二分。于是问题转换为最小权任意匹配。因为 \(m\) 只有 \(4\),使用轮廓线DP即可在 \(O(nm2^m)\) 时间内解决问题。

    需要注意的是本题二分的边界。或许会认为仅仅是 \(10^9\) 就行了,但考虑一条长度为 \(nm\)\(1\)\(10^9\) 交错的链,且链的开头结尾都是 \(10^9\),就会发现最后一条边的斜率是 \(10^9\times nm\) 级别的。于是要把边界开到 \(10^{14}\),这样能保证不爆 long long,同时还能求出答案。

    时间复杂度 \(O(nm2^m\log 10^{14})\)

    代码:

    #include<bits/stdc++.h>
    using namespace std;
    typedef long long ll;
    int T,n,m,q,X[40100][4],Y[40100][4],F[40100][4][1<<4],G[40100][4][1<<4],lim;
    ll f[40100][4][1<<4];
    void chmn(int i,int j,int k,int K,ll bon,bool mat){
    	int I=i-!j,J=(!j?m:j)-1;
    	if(f[i][j][k]>f[I][J][K]+bon)f[i][j][k]=f[I][J][K]+bon,F[i][j][k]=F[I][J][K]+mat,G[i][j][k]=G[I][J][K]+mat;
    	else if(f[i][j][k]==f[I][J][K]+bon)F[i][j][k]=min(F[i][j][k],F[I][J][K]+mat),G[i][j][k]=max(G[i][j][k],G[I][J][K]+mat);
    }
    int che(ll ip){
    //	printf("%d\n",ip);
    	for(int i=0;i<n;i++)for(int j=0;j<m;j++){
    		if(!i&&!j){for(int k=0;k<lim;k++)f[i][j][k]=0;continue;}
    		for(int k=0;k<lim;k++)f[i][j][k]=0x3f3f3f3f3f3f3f3f;
    		for(int k=0;k<lim;k++){
    			if(i&&!(k&(1<<j)))chmn(i,j,k|(1<<j),k,X[i][j]-ip,true);
    			if(j&&!(k&(1<<(j-1))))chmn(i,j,k|(1<<(j-1))|(1<<j),k,Y[i][j]-ip,true);
    			chmn(i,j,k&(lim-1-(1<<j)),k,0,false);
    		}
    	}
    	ll mn=0x3f3f3f3f3f3f3f3f;
    	for(int k=0;k<lim;k++)mn=min(mn,f[n-1][m-1][k]);
    	int L=0x3f3f3f3f,R=0;
    	for(int k=0;k<lim;k++)if(mn==f[n-1][m-1][k])L=min(L,F[n-1][m-1][k]),R=max(R,G[n-1][m-1][k]);
    	if(L>q)return -1;
    	if(R<q)return 1;
    	printf("%lld\n",mn+ip*q);
    	return 0;
    }
    void read(int &x){
    	x=0;
    	char c=getchar();
    	while(c>'9'||c<'0')c=getchar();
    	while(c>='0'&&c<='9')x=(x<<3)+(x<<1)+(c^48),c=getchar();
    }
    int main(){
    	read(T);
    	while(T--){
    		read(n),read(m),read(q),lim=1<<m;
    		for(int i=1;i<n;i++)for(int j=0;j<m;j++)read(X[i][j]);
    		for(int i=0;i<n;i++)for(int j=1;j<m;j++)read(Y[i][j]);
    		ll l=0,r=1e14,mid;
    		while(true){
    			int tp=che(mid=(l+r)>>1);
    			if(tp==-1)r=mid-1;
    			if(tp==1)l=mid+1;
    			if(!tp)break;
    		}
    	}
    	return 0;
    }
    

  • 相关阅读:
    设计模式
    软件的架构与设计模式之经典架构模式简介
    Rose与PowerDesigner:两款建模工具的对比
    C#中Socket多线程编程实例 [转载]
    C#串口控制
    .NET反射、委托技术与设计模式
    求多个数的质因子
    求单个数的欧拉函数
    基本欧拉函数
    hdu 2157(矩阵的快速幂)
  • 原文地址:https://www.cnblogs.com/Troverld/p/14601535.html
Copyright © 2011-2022 走看看