码迷,mamicode.com
首页 > 其他好文 > 详细

Kabloom——题解

时间:2019-03-21 21:42:54      阅读:189      评论:0      收藏:0      [点我收藏+]

标签:代码注释   ons   去掉   sam   pre   循环   using   一个   ase   

  • 题目:

Problem

给定两叠各有n张的扑克牌,牌的种类有A,2,3,4,5,6,7,8,9,T,J,Q,K,R,其中A表示Aces,2到10为数字牌,其中10用字母T表示,J,Q,K为花牌,R表示王。
你可以再两叠牌中各去掉若干张牌,但不能改变牌之间的相对顺序。若两叠牌的对应位置上的纸牌相同,则构成一对,并获得相应的分数。
A的分数是20,花牌的分数是15,数字牌的分数为数字的大小。王牌可以被用作任意牌派对,其分数由与派对的牌的决定,
如一个王和一个A配对分数为20,和花牌派对的分数为15,和数字牌派对的分数为数字的大小。特殊的,两个王派对的分数为50。

请计算最大分数和。注意,一对牌的分数是牌的分数的两倍,比如一对A的分数是20×2=40

Input Data

第一行,一个整数n。
第二行,n个字符,表示第一叠纸牌。
第三行,n个字符,表示第二叠纸牌。

Output Data

一个整数,表示最大的分数和。

 Input / Output Sample
9
6 3 7 4 2 A K R T
3 5 4 7 R A Q K T
140

Data Limit

10n2000

Problem Source

hackerrank

  • 分析:

  1. 最早想到的是搜索,但一看n的范围。。。(⊙o⊙)…
    所以,DP在所难免!
  2. 用DP就得分析状态的转移:
     首先分析数组f[i][j]所代表的含义。这里定义:表示做到第一叠牌的第i张,第二叠牌的第j张时的最大得分。
     其次,分析f[i][j]可以由三个状态转移而来:
            1、f[i-1][j]:略过第一副牌的这张牌,直接取上一次的分数(你可以再两叠牌中各去掉若干张牌)。
            2、f[i][j-1]:略过第二副牌的这张牌。
            3、f[i-1][j-1]+得分:两张牌都不略过(就是要配对得分),但需要一个前提:两张牌相等或者有一个为王(可以转换)。满足这个条件,就可以进行第三              次的比较。同时,为了方便,写一个函数score来计算每次的得分,该函数根据题目编写,详见代码注释。
    最后,f[n][n]就是在第一叠牌第n张,第二叠牌第n张时,得到的最大值了。但注意,题目要求*2!
  3. 这样,只需要两重循环,n方的时间复杂度,2000的平方就可以过了。
  • 代码:

 1 #include<bits/stdc++.h>
 2 using namespace std;
 3 const int MAXN=2000+5;
 4 int score(char x,char y)
 5 {
 6     if(x==R && y==R) return 50;//两个王,不用想。
 7     //注意,两个王的情况必须先处理,否则会进入if而没有输出!
 8     if(x==R)
 9     {
10         if(y==A) return 20;//可以根据另个数进行变化
11         if(y==Q || y==K || y==J) return 15;
12         if(y==T) return 10;
13         return y-0;//不是字母,就是数字了。
14     }
15     if(y==R)//y同x一样
16     {
17         if(x==A) return 20;
18         if(x==Q || x==K || x==J) return 15;
19         if(x==T) return 10;
20         return x-0;
21     }
22     //所有王的情况都不是,剩下的肯定是两个相同的、不是王的情况。
23     if(x==A) return 20;
24     if(x==Q || x==K || x==J) return 15;
25     if(x==T) return 10;
26     return x-0;//和上面一样
27 }
28 char a[MAXN],b[MAXN];
29 int n,f[MAXN][MAXN];
30 int main()
31 {
32     cin>>n;
33     for(int i=1;i<=n;i++) 
34     cin>>a[i];
35     for(int i=1;i<=n;i++)
36     cin>>b[i];
37     //2000数据,不算特别大,暂且用个cin
38     for(int i=1;i<=n;i++)
39     for(int j=1;j<=n;j++)
40     {
41         f[i][j]=max(f[i-1][j],f[i][j-1]);
42         if(a[i]==b[j] || a[i]==R || b[j]==R)
43         f[i][j]=max(f[i][j],f[i-1][j-1]+score(a[i],b[j]));
44     }
45     printf("%d\n",f[n][n]*2);
46     return 0;
47 }    

 

Kabloom——题解

标签:代码注释   ons   去掉   sam   pre   循环   using   一个   ase   

原文地址:https://www.cnblogs.com/yuyer/p/10574729.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!