• SPOJ 4053


    我们的男主现在手中有n*c张牌,其中有c(<=4)种颜色,每种颜色有n(<=100)张,现在他要排序,首先把相同的颜色的牌放在一起,颜色相同的按照序号从小到大排序。现在他想要让牌的移动次数最小,问移动的最小次数是多少。

    【LIS】因为颜色种类相当少,可以枚举排序后颜色的次序。相同颜色的纸牌从小到大排序,所以所有纸牌的最终顺序也就确定了。

    然后就是怎么样移动纸牌能够使纸牌成为最终的顺序。

    因为从给定序到有序的移动次数等于从有序到给定序,所以我们反着想,对于有序的序列,移动一张纸牌,那么它的最长不降序列就减少1。如果移动多个呢,只要求出其中没有改变的最大长度即可,这个长度就是原序列的最长不降序列。

    一般的,如果给定序的最长不降序列是x,那么到有序状态的移动次数一定是n*c-x

    #include<bits/stdc++.h>
    #define eps 1e-9
    #define FOR(i,j,k) for(int i=j;i<=k;i++)
    #define MAXN 1005
    #define MAXM 40005
    #define INF 0x3fffffff
    using namespace std;
    typedef long long LL;
    struct node
    {
        int c,w,hash;
    }p[505];
    
    int i,j,k,n,m,x,y,T,ans,big,cas,num,len;
    bool flag;
    int ord[5],c;
    bool vis[5];
    
    bool cmp(node a,node b)
    {
        return a.hash<b.hash;
    }
    
    void work()
    {
        for (int i=1;i<=n*c;i++)
        {
            p[i].hash=ord[p[i].c]*1000+p[i].w;//给每个元素一个唯一标识,按照这个标识来求最长不下降子序列
        }
        
        int dp[505],num;
        dp[0]=0;
        num=0;
        for (int i=1;i<=n*c;i++)
        {
            if (p[i].hash>=dp[num])
            {
                dp[++num]=p[i].hash;
                
            }else
            {
                k=upper_bound(dp+1,dp+1+num,p[i].hash)-dp; 
                dp[k]=p[i].hash;
            }
        }
        
        ans=min(ans,n*c-num);
    }
        
        
    
    void dfs(int f)
    {
        for (int i=1;i<=c;i++)
        {
            if (!vis[i])
            {
                vis[i]=1;
                ord[f]=i;
                if (f==c) work();else dfs(f+1);//枚举完毕后进入work()计算最长不下降子序列
                vis[i]=0;
            }
        }
    }
    
    int main()
    {
        scanf("%d%d",&c,&n);
        ans=INF;
         for (i=1;i<=c*n;i++)
         {
            scanf("%d%d",&p[i].c,&p[i].w);
         }
         memset(vis,0,sizeof(vis));
         dfs(1);//DFS枚举颜色次序
         printf("%d
    ",ans);
        return 0;
    }
  • 相关阅读:
    ubuntu9.10在AMD 双核上的安装
    修改wamp默认安装下MySQL的root账户密码
    IE6 IE7 IE8 火狐浏览器兼容问题
    在windows xp下安装ubuntu9.10
    制作Ubuntu U 盘启动盘在ubuntu12.04中
    使用StackTraceElement封装,打印调试代码!
    String字符串拼接原理剖析
    List中的数据如何根据对象的某一个或多个字段排序引出Comparable和comparator的使用
    String类的split方法
    通过例子看六种异常处理的陋习
  • 原文地址:https://www.cnblogs.com/zhyfzy/p/4285484.html
Copyright © 2020-2023  润新知