【二进制枚举+LCS】Card Hand Sorting

【二进制枚举+LCS】Card Hand Sorting

题目描述

When dealt cards in the card game Plump it is a good idea to start by sorting the cards in hand by suit and rank. The different suits should be grouped and the ranks should be sorted within each suit. But the order of the suits does not matter and within each suit, the cards may be sorted in either ascending or descending order on rank. It is allowed for some suits to be sorted in ascending order and others in descending order.
Sorting is done by moving one card at a time from its current position to a new position in the hand, at the start, end, or in between two adjacent cards. What is the smallest number of moves required to sort a given hand of cards?

输入

The ?rst line of input contains an integer n (1 ≤ n ≤ 52), the number of cards in the hand. The second line contains n pairwise distinct space-separated cards, each represented by two characters. The ?rst character of a card represents the rank and is either a digit from 2 to 9 or
one of the letters T , J , Q , K , and A representing Ten, Jack, Queen, King and Ace, respectively, given here in increasing order. The second character of a card is from the set { s , h , d , c } representing the suits spades ?, hearts ?, diamonds ?, and clubs ?.

输出

Output the minimum number of card moves required to sort the hand as described above.

样例输入

7
9d As 2s Qd 2c Jd 8h

样例输出

2

看一眼,52,嗯 状态压缩 暴力 二进制枚举?然后,怎么换啊,不会。好难。。。
比赛结束,LCS,嗯,会了
LCS差点不会写...尴尬
通过移位符判断位置。

#include<bits/stdc++.h>
using namespace std;
#define ll long long
map<char,int>mp;
inline void init()
{
    for(int i=2;i<=9;++i){
        mp[i+'0']=i;
    }
    mp['T']=10;
    mp['J']=11;
    mp['Q']=12;
    mp['K']=13;
    mp['A']=14;
    mp['s']=0;
    mp['h']=1;
    mp['d']=2;
    mp['c']=3;
}
struct node
{
    int id;
    int val;
    int block;
    int k;
}s[55];
int dp[55],n;
inline bool cmp(node x,node y)
{
    if(x.k==y.k){
        return x.val<y.val;
    }
    return x.k<y.k;
}
inline int lcs(){
   memset(dp,0,sizeof(dp));
   int ans=1;
   dp[0]=1;
   for(int i=1;i<n;++i){
        dp[i]=1;
    for(int j=0;j<i;++j){
        if(s[i].id>s[j].id){
            dp[i]=max(dp[j]+1,dp[i]);
        }
    }
    ans=max(dp[i],ans);
   }
   return ans;
}
int main()
{
    init();
    scanf("%d",&n);
    char str[3];
    for(int i=0;i<n;++i){
        scanf("%s",str);
        s[i].val=mp[str[0]];
        s[i].block=mp[str[1]];
        s[i].id=i;
    }
    int arr[4]={0,1,2,3},ans=1e9;
    do{
        for(int i=0;i<16;++i){
            for(int j=0;j<n;++j){
                s[j].k=arr[s[j].block];
                s[j].val=abs(s[j].val)*(((i>>s[j].k)&1)!=1?-1:1);
            }
            sort(s,s+n,cmp);
            ans=min(ans,n-lcs());
        }
    }while(next_permutation(arr,arr+4));//全排列
    printf("%d\n",ans);
    return 0;
}

原文地址:https://www.cnblogs.com/smallocean/p/9749053.html

时间: 2024-08-29 22:05:12

【二进制枚举+LCS】Card Hand Sorting的相关文章

upc 3028 Card Hand Sorting

Card Hand Sorting 时间限制: 1 Sec  内存限制: 64 MB提交: 66  解决: 23[提交] [状态] [讨论版] [命题人:外部导入] 题目描述 When dealt cards in the card game Plump it is a good idea to start by sorting the cards in hand by suit and rank. The different suits should be grouped and the ra

UVa 818 切断圆环链(dfs+二进制枚举)

https://vjudge.net/problem/UVA-818 题意:有n个圆环,其中有一些已经扣在了一起.现在需要打开尽量少的圆环,使得所有圆环可以组成一条链,例如,有5个圆环,1-2,2-3,4-5,则需要打开一个圆环,如圆环4,然   后用它穿过圆环3和圆环5后再次闭合4,就可以形成一条链:1-2-3-4-5. 思路:从n个圆环中任意选择圆环,这就是枚举子集.所以这道题目可以用二进制枚举来做. 那么如何判断当前打开圆环是可行的呢?在去除打开的圆环后需要判断: ①:每个圆环的分支数都必

UVa818 Cutting Chains (二进制枚举)

链接:http://vjudge.net/problem/35523 分析:links记录初始圆环链的情况,然后二进制枚举编号为0~n-1的圆环哪个被打开了,一个圆环最多一个前驱和一个后继,所以judge判断如果有一个未打开的圆环同时和2个以上的未打开圆环相连就一定不能形成链,剪去.circle判断剩下的未打开圆环是否形成环,以及若未成环那么有多少条单链links_num,注意最后成链不用按顺序比如1->2->3...这样.然后判断一下打开的圆环数够不够把links_num条单链扣成一条链,若

POJ 2436 二进制枚举+位运算

题意:给出n头牛的得病的种类情况,一共有m种病,要求找出最多有K种病的牛的数目: 思路:二进制枚举(得病处为1,否则为0,比如得了2 1两种病,代号就是011(十进制就是3)),首先枚举出1的个数等于k的二进制数,然后跟所有的牛的代号一一比较,符合的           +1,找出其中和最大的:就是转换2进制麻烦,用位运算就好实现了,但是位运算不是很明白含义,明白了再补充: 知识点: 3 & 2 = 2,相同为1,不同为0, 011 & 010 = 010:(怎么利用的这个特点不明白):

1151 - Buy or Build(二进制枚举子集 + 并查集)

这题LRJ书上翻译的有问题,书上说两点之间的cost是两点的欧几里得距离,而题目要求两点的距离是两点欧几里得距离的平方. 其余就没什么好说的了,裸的并查集,需要注意的就是二进制枚举子集的问题. 二进制枚举子集: for(int i = 0 ; i < (1 << s) ; i++){ /*s是集合元素的个数*/ for(int j = 0 ; j < s ; j++){ if(!(s >> j) & 1) continue; else{ } } } 140548

UvaLive 6661 Equal Sum Sets 二进制枚举/DP

链接:http://vjudge.net/problem/viewProblem.action?id=49406 题意:根据给出的n,k,s求出n个数每个数都不大于k,和为s的序列(n个数每个都不同)的总情况数. 思路: 1.二进制枚举枚举出所有可能排列,并求和若和为s,则符合,否则不符合. 代码: #include<iostream> #include<set> #include<map> #include<queue> #include<cstri

wikioi 2144 分步二进制枚举+map记录

题目描述 Description 有n个砝码,现在要称一个质量为m的物体,请问最少需要挑出几个砝码来称? 注意一个砝码最多只能挑一次 输入描述 Input Description 第一行两个整数n和m,接下来n行每行一个整数表示每个砝码的重量. 输出描述 Output Description 输出选择的砝码的总数k,你的程序必须使得k尽量的小. 样例输入 Sample Input 3 10 5 9 1 样例输出 Sample Output 2 数据范围及提示 Data Size & Hint 1

CUGBACM_Summer_Tranning1 二进制枚举+模拟+离散化

整体感觉:这个组队赛收获还挺多的.自从期末考试以后已经有一个多月没有 做过组队赛了吧,可是这暑假第一次组队赛就找回了曾经的感觉.还挺不错的!继续努力!! 改进的地方:这次组队赛開始的时候题目比較难读懂,然后就感觉题目应该比較难吧,认为应该是区域赛难度的题目.尽管A题和B题自己都感觉能自己A的.可是可能对自己不太自信,所以让队友大帝敲了.要是当时自己敢敲一下的话,后续会更快的A掉吧. A题:二进制枚举 题目链接:https://icpcarchive.ecs.baylor.edu/external

二进制枚举

2017-08-03 11:34:36 writer:pprp 一个知识点,之前从来没有遇到,最近的集训中频繁用到这个,学习理解了 代码及分析如下: // 二进制枚举 // 用来解决例如下边这样的问题 // 给你一串数列,要你将其中所有可能出现的sum找出来,就是说每个数都有两个状态,选或者是不选, //那么就选择用二进制通过 0 1 来表示选还是不选 #include <iostream> using namespace std; int main() { int n; //这里n意思是需要