第一题:马戏团
题目
搜狐员工小王最近利用假期在外地旅游,在某个小镇碰到一个马戏团表演,精彩的表演结束后发现团长正和大伙在帐篷前激烈讨论,小王打听了下了解到, 马戏团正打算出一个新节目“最高罗汉塔”,即马戏团员叠罗汉表演。考虑到安全因素,要求叠罗汉过程中,站在某个人肩上的人应该既比自己矮又比自己瘦,或相等。 团长想要本次节目中的罗汉塔叠的最高,由于人数众多,正在头疼如何安排人员的问题。小王觉得这个问题很简单,于是统计了参与最高罗汉塔表演的所有团员的身高体重,并且很快找到叠最高罗汉塔的人员序列。 现在你手上也拿到了这样一份身高体重表,请找出可以叠出的最高罗汉塔的高度,这份表中马戏团员依次编号为1到N。
![]()
分析
动态规划问题,可以先用一个vector<vector<int>>存放员工数据。先以体重做比较进行增序排序。排序完后,找出身高的最长递增子序列长度。
代码
#include<iostream>
#include<algorithm>
using namespace std;
struct player{
int w;
int h;
};
bool com_w(player p1, player p2)
{
//按照体重从小到大排序
if(p1.w!=p2.w)
return p1.w<=p2.w;
//在体重相等的条件下,身高高的在前(在上)
else
return p1.h>p2.h;
}
int main()
{
int N;
int h;
int w;
int index;
vector<player> p;
while(cin>>N)
{
p.clear();
for(int i=0;i<N;i++)
{
player pt;
cin>>index>>w>>h;
pt.w=w;
pt.h=h;
p.push_back(pt);
}
sort(p.begin(),p.end(),com_w);
//按身高求最大上升子序列
int dp2[N+1];
int max=0;
dp2[0]=1;
for(int i=1;i<N;i++)
{
dp2[i]=1;
for(int j=0;j<i;j++)
{
if(p[j].h<=p[i].h && dp2[j]+1 > dp2[i])
dp2[i]=dp2[j]+1;
}
}
for(int i=0;i<N;i++)
if(max<dp2[i]) max=dp2[i];
cout<<max<<endl;
}
return 0;
}
第二题:扎金花
题目
两个搜狐的程序员加了一个月班,终于放假了,于是他们决定扎金花渡过愉快的假期 。
游戏规则:
共52张普通牌,牌面为2,3,4,5,6,7,8,9,10,J,Q,K,A之一,大小递增,各四张; 每人抓三张牌。两人比较手中三张牌大小,大的人获胜。
对于牌型的规则如下:
- 三张牌一样即为豹子
- 三张牌相连为顺子(A23不算顺子)
- 有且仅有两张牌一样为对子,豹子>顺子>对子>普通牌型, 在牌型一样时,比较牌型数值大小(如AAA>KKK,QAK>534,QQ2>10104) 在二人均无特殊牌型时,依次比较三张牌中最大的。大的人获胜,如果最大的牌一样,则比较第二大,以此类推(如37K>89Q) 如二人牌面相同,则为平局。
![]()
代码
import java.util.Scanner;
public class Main {
public static void main(String[] args) {
Scanner scan = new Scanner(System.in);
while (scan.hasNextLine()) {
String s1 = scan.next();
String s2 = scan.next();
char[] c1 = s1.trim().replaceAll("0", "").toCharArray();
char[] c2 = s2.trim().replaceAll("0", "").toCharArray();
scan.nextLine();
// try{
System.out.println(new Main().new pai(c1).compareTo(new Main().new pai(c2)));
//}catch(Exception e){
// System.out.println(-2);
// }
}
}
class pai implements Comparable<pai> {
private final static int BAO = 3;
private final static int SHUN = 2;
private final static int DUI = 1;
private final static int PU = 0;
private final static int LO = 10;
private final static int J = 11;
private final static int Q = 12;
private final static int K = 13;
private final static int A = 14;
private int rank;
private int[] sanpai;
private char[] stringPai;
public pai(char[] c1) {
stringPai = c1;
sanpai = digitPai();
SortPai();
setRank();
}
private int[] digitPai() {
sanpai = new int[stringPai.length];
for (int i = 0; i < stringPai.length; i++) {
if (stringPai[i] == '1')
sanpai[i] = 10;
else if (stringPai[i] == 'J' || stringPai[i] == 'j')
sanpai[i] = 11;
else if (stringPai[i] == 'K' || stringPai[i] == 'k')
sanpai[i] = 13;
else if (stringPai[i] == 'Q' || stringPai[i] == 'q')
sanpai[i] = 12;
else if (stringPai[i] == 'a' || stringPai[i] == 'A')
sanpai[i] = 14;
else
sanpai[i] = Integer.parseInt("" + stringPai[i]);
}
return sanpai;
}
private void setRank() {
if (sanpai[0] == sanpai[1] && sanpai[0] == sanpai[2])
rank = BAO;
else if (sanpai[0] != sanpai[1] && sanpai[1] != sanpai[2])
rank = PU;
else if (sanpai[0] - 1 == sanpai[1] && sanpai[1] - 1 == sanpai[2])
rank = SHUN;
else
rank = DUI;
}
public int[] getSanpai() {
return sanpai;
}
public int getRank() {
return rank;
};
private void SortPai() {
for (int i = 0; i < sanpai.length; i++)
for (int j = i + 1; j < sanpai.length; j++) {
if (sanpai[i] < sanpai[j]) {
sanpai[i] = sanpai[i] ^ sanpai[j];
sanpai[j] = sanpai[i] ^ sanpai[j];
sanpai[i] = sanpai[i] ^ sanpai[j];
}
}
};
public int compareTo(pai o) {
if (this.getRank() > o.getRank())
return 1;
else if (this.getRank() < o.getRank())
return -1;
else
for (int i = 0; i < sanpai.length; i++) {
if (sanpai[i] > o.getSanpai()[i])
return 1;
else if (sanpai[i] < o.getSanpai()[i])
return -1;
}
// if()
return 0;
}
}
}
第三题:发奖金
题目
狐进行了一次黑客马拉松大赛,全公司一共分为了N个组,每组一个房间排成一排开始比赛,比赛结束后没有公布成绩,但是每个组能够看到自己相邻的两个组里比自己成绩低的组的成绩,比赛结束之后要发奖金,以1w为单位,每个组都至少会发1w的奖金,另外,如果一个组发现自己的奖金没有高于比自己成绩低的组发的奖金,就会不满意,作为比赛的组织方,根据成绩计算出至少需要发多少奖金才能让所有的组满意。
![]()
分析
对于给定的一堆成绩,从开始往后,第一个初始化为 1W ,依次向后初始化 i +1 的 money 值,当 i 对应的分数比 i+1 的分数小时, i+1 应该拿到更多的前,所以有 money[i+1]=money[i]+1;当 i 对应的分数跟 i+1 相等时,反正也看不到,将 money[i+1] 设为 1 ;当 i 对应的分数比 i +1 大时: money[i+1] 应该是此时较小的,将其设为 1 ,但是可能后面的跟他相同或比他小,因此要将后面分数递增的那些 money 跟新一下,此处采用一个 for 循环,循环从 k=i+1 开始,当 score[k-1]>score[k]&&money[k]+1>money[k-1] 时才 – ,注意与后面的条件,是为了判断 money 值可能的断崖式下降(因为起始 money[i+1] 设为 1 了,可能比 money[i] 小很多)。满足条件将其值加 1.最后累加
代码
#include<iostream>
#include<vector>
using namespace std;
int main()
{
int n;
while(cin>>n)
{
vector<int>a(n,0);
for(int i=0;i<n;i++)
cin>>a[i];
vector<int>b(n,1);
for(int i=1;i<n;i++)//从前往后
if(a[i]>a[i-1])
b[i]=b[i-1]+1;
for(int i=n-2;i>=0;i--)//从后往前
if(a[i]>a[i+1]&&b[i]<b[i+1]+1)
b[i]=b[i+1]+1;
long sum=0;
for(int i=0;i<n;i++)
sum+=b[i];
cout<<sum<<endl;
}
}