zoukankan      html  css  js  c++  java
  • 从加工生产调度看邻项交换问题

    题目链接

    这类题目显然是邻项交换,但是有要注意的点。

    先用邻项交换的方法跑一边,发现(cmp)函数为:(x.a+max(x.b,y.a)+y.b < y.a+max(y.b,x.a)+x.b)

    其实可以化简:(min(x.a,y.b)<min(x.b,y.a))(因为(max(x,y)-x-y=-min(x,y))

    但是这是一个错的排序方式,所以说这个证明及其完全我就不写了

    我感性理解了一下,就是化简后有(max,min)函数之类的好像都不行。

    网上很多人说这个式子没有传递性,实际上这个式子不满足不可比的传递性。

    而这个传递性可以理解成三个元素(a,b,c)对于某个不等关系满足(a=b,b=cRightarrow a=c)。(这是个不完全的理解,但暂时可以这么理解,泛用性应该还不差)

    实际上,我们这样带有(max,min)函数的式子一般不满足,拿此题来说对于以下的三个产品就不满足:

    7 3
    1 1
    1 6
    

    至此我们先强调一点,我并没有说(Johnson)算法是错的,实际上从原理上来说,这个要求是完全正确,也就是说,我们的最优排序方案一定满足这个式子,用这个式子人工排序也一定能成,但是在计算机中行,因为sort的排序方式是一定会满足不可比的传递性,也就是说两个数相等对其顺序没有影响,但是这种排序方式不一定,所以我们要将其转化,化为满足不可比的传递性的形式。

    换句话说,我们要找到一种等价的比较方式,使的无论什么情况下均满足上面的式子且具有不可比的传递性。

    转换的时候实际上我们并不是说完全抛弃掉原来的方式,观察(Hack)样例,实际上就是当有(a_i==b_i)时会出锅。

    也就是说,我们将这种情况单独领出来考虑即可:

    • (a_i<b_i&&a_j=b_j)时不用交换(分类讨论)
    • (a_i>b_i&&a_j=b_j)时需要交换(分类讨论)

    所以我们得到了如下的分类(每一类的顺序即为其优先级):

    • (a_i<b_i&&a_j<b_j),这时可以用(min(x.a,y.b)<min(x.b,y.a))(或者你可以说按照(a_i<a_j)排序,因为你分类讨论之后发现这两者一样)
    • (a_i=b_i),这时随意(自行讨论)。
    • (a_i>b_i&&a_j>b_j),这时可以用(min(x.a,y.b)<min(x.b,y.a))(或者你可以说按照(b_i>b_j)排序,因为你分类讨论之后发现这两者一样)

    这时我们就可以写了。

    #include<bits/stdc++.h>
    using namespace std;
    #define int long long
    inline int read()
    {
        int f=1,w=0;char x=0;
        while(x<'0'||x>'9') {if(x=='-') f=-1; x=getchar();}
        while(x!=EOF&&x>='0'&&x<='9') {w=(w<<3)+(w<<1)+(x^48);x=getchar();}
        return w*f;
    }
    const int N=20010;
    int n,f[N];
    struct Person
    {
    	int x,y,d,id;
    	bool operator < (const Person &b)
    		{
    			return d==b.d?min(x,b.y)<min(y,b.x):d<b.d;
    		}
    }p[N];
    main(){
    #ifndef ONLINE_JUDGE
        freopen("A.in","r",stdin);
    #endif
    	n=read();
    	for(int i=1;i<=n;i++) p[i].x=read(),p[i].id=i;
    	for(int i=1;i<=n;i++)
    	{
    		p[i].y=read();
    		p[i].d=p[i].x<p[i].y?-1:p[i].x>p[i].y?1:0;
    	}
    	sort(p+1,p+n+1);
    	int Ta=p[1].x,Tb=p[1].x+p[1].y;
    	for(int i=2;i<=n;i++) Tb=max(Ta+p[i].x,Tb)+p[i].y,Ta+=p[i].x;
    	printf("%lld
    ",Tb);
    	for(int i=1;i<=n;i++) printf("%lld ",p[i].id);
    }
    

    其实还有一种做法:我们发现(Tb=max(Ta+p[i].x,Tb)+p[i].y,Ta+=p[i].x;)是我们求答案的过程。

    就是(懒得打了)

    没错,就是皇后游戏,观察全局,发现和(a_i)的大小有关,因此当我们判到(min(x.a,y.b)=min(x.b,y.a))时,可以按照(a_i<a_j)的顺序排序(应该本质上是一样的,只是这样更好理解。)

    皇后游戏的代码:

    #include<bits/stdc++.h>
    using namespace std;
    #define int long long
    inline int read()
    {
        int f=1,w=0;char x=0;
        while(x<'0'||x>'9') {if(x=='-') f=-1; x=getchar();}
        while(x!=EOF&&x>='0'&&x<='9') {w=(w<<3)+(w<<1)+(x^48);x=getchar();}
        return w*f;
    }
    const int N=20010;
    int n,f[N];
    struct Person
    {
    	int x,y;
    	bool operator < (const Person &b)
    		{
    			return min(x,b.y)==min(y,b.x)?x<b.x:min(x,b.y)<min(y,b.x);
    		}
    }p[N];
    main(){
    #ifndef ONLINE_JUDGE
        freopen("A.in","r",stdin);
    #endif
    	int T=read();
    	while(T--)
    	{
    		int Tot=0,ans=0;n=read();
    		for(int i=1;i<=n;i++) p[i].x=read(),p[i].y=read();
    		sort(p+1,p+n+1);
    		for(int i=1;i<=n;i++)
    			Tot+=p[i].x,ans=max(ans,Tot)+p[i].y;
    		printf("%lld
    ",ans);
    	}
    }
    
  • 相关阅读:
    SQL Server 2008中的hierarchyid
    SQL判断空值、nvl处理与JOIN的使用
    Transact-SQL语法速查手册
    MySQL连接字符串
    如何让spark sql写mysql的时候支持update操作
    基于calcite做傻瓜式的sql优化(三)
    基于calcite做傻瓜式的sql优化(二)
    基于calcite做傻瓜式的sql优化(一)
    spark升级:从1.6升级到2.4.6的记录
    彻底解决,sparkSQL读取csv中Map字段类型的问题
  • 原文地址:https://www.cnblogs.com/wo-shi-zhen-de-cai/p/11553033.html
Copyright © 2011-2022 走看看