Card Hand Sorting Kattis - cardhand
 
题意
 
将n张扑克牌排序,排序规则,不同花色之间的顺序没有要求,同意花色之间必须升序或者降序,问使得整个扑克牌排好序最少需要移动多少次
 
分析
 
知识点
 
组合数学,状态压缩,最长上升子序列  花色之间的排序 
  
   4!
  
   
    
     4
    
    
     !
    
     升序或者降序 
  
   24
  
   
    
     
      2
     
     
      4
     
    
     共有
  
   t=4!∗24
  
   
    
     t
    
    
     =
    
    
     4
    
    
     !
    
    
     ∗
    
    
     
      2
     
     
      4
     
    
    中情况,对于这t中情况,分别对每一中情况求LCS,求出LCS最长的就是要求的最有排列,因为这意味着,最长上升子序列中的元素不用移动
 
参考代码
 
#include <iostream>
#include <vector>
#include <map>
#include <algorithm>
using namespace std;
template <
class It>
int LCS(It begin,It end)
{
    
typedef typename iterator_traits <It>::value_type T;
    T inf = 
1<<
30;
    
vector<T> Best(end-begin,inf);
    
for(It i = begin ; i != end; ++i)
        *lower_bound(Best.begin(),Best.end(),*i) = *i;
    
return lower_bound(Best.begin(),Best.end(),inf) - Best.begin();
}
int main(
void)
{
    
std::ios::sync_with_stdio(
false);
    
map<char,int> ma;
    ma[
'T'] = 
10;
    ma[
'J'] = 
11;
    ma[
'Q'] = 
12;
    ma[
'K'] = 
13;
    ma[
'A'] = 
14;
    
map<char,int> color;
    color[
's'] = 
0;
    color[
'h'] = 
1;
    color[
'd'] = 
2;
    color[
'c'] = 
3;
    
int n;
    
char s[
3];
    
int num[
100];
    
int col[
100];
    
int value[
100];
    
while(
cin>>n)
    {
        
for(
int i = 
0; i < n; ++i)
        {
            
cin>>s;
            
if(ma.count(s[
0]))
                num[i] = ma[s[
0]];
            
else
                num[i] = s[
0] - 
'0';
            col[i] = color[s[
1]];
        }
        
int ans = 
0;
        
int q[] = {
0,
1,
2,
3};
        
do
        {
            
for(
int dir = 
0; dir < 
16; ++dir)
            {
                
for(
int i = 
0; i < n; ++i)
                    value[i] = q[col[i]] * 
100 + num[i] * (
1- 
2*!!(dir&(
1<<col[i])));
                ans = max(ans,LCS(value,value+n));
            }
        }
        
while(next_permutation(q,q+
4));
        
cout<<n-ans<<endl;
    }
    
return 0;
}