【在线笔试题解题报告系列】Indeed Tokyo 2017校园招聘 在线测试3(时间:2016.07.09)

……这个在线测试赛后不可练习,题目也看不了了,但是代码我都好好的留下来了

先上提交记录:

【在线笔试题解题报告系列】Indeed Tokyo 2017校园招聘 在线测试3(时间:2016.07.09)_第1张图片


之后从前往后复述题意,写题解吧。


本文地址:http://blog.csdn.net/fcxxzux/article/details/51931463

Problem A - Alphabet Replacement

题意:给你2个长度相等的,由小写字母组成的字符串。现在允许你做一个操作:把2个字符串中出现的字符A换成字符B(允许自己换成自己,2个字符串里出现的字符A都要被替换),问有没有一种替换方案,使得替换后2个字符串完全一样?

比如,输入:

ababcd

babacd

输出Yes,因为可以通过把a换成b,使得2个字符串都变成bbbbcd。


——英文题面描述的题意有毒,当搞懂正确题意后,还是很白送的:暴力枚举所有替换方案,并检查

也就26*26*length,这里length还只有100,直接交。

#include 
#include 
#include 
#include 
#include 
#include 
#include 
using namespace std;
typedef long long ll;

char sa[105],sb[105];
int len;

char change(char x,char s,char g){
    return x==s?g:x;
}

bool check(char src,char goal){
    for(int i=0;i


Problem B - Marathon Runners

2个人Takahashi和Aoki站在起跑线上。已知:

1、发令枪响后,Takahashi立刻出发,Aoki将延迟0.5秒出发

2、已知Takahashi跑一圈用a秒,Aoki跑一圈用b秒(a和b都是整数)

求:第k次有人冲过起点线的时候,是谁冲过的?


比如a=3 b=2 k=1,输出Aoki,a=3 b=2 k=2,输出Takahashi

从起点出发不算冲过起点线,之后2.5秒的时候Aoki冲过起点线,3秒的时候Takahashi才冲过起点线,下一次是Aoki在4.5秒冲过,再之后是Takahashi在6秒冲过,之后Aoki在6.5和8.5秒各自冲过一次,9秒的时候Takahashi再冲过。



做法:因为k实在不大(k<=100000),所以,与其写二分搜索伤害自己,不如,模拟。

采用事件触发的思路,记录每个人下次冲过起点线的时间(timer被触发的时刻),之后循环判断谁冲过起点线,并更新他下次冲过起点线的时间。

注意由于a,b<=100000,导致时刻超过32位整型的表示范围,请使用64位整型。

#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
using namespace std;
typedef long long ll;

template 
inline void scan(T &ret) {
    char c; ret=0;
    while((c=getchar())<'0'||c>'9');
    while(c>='0'&&c<='9') ret=ret*10+(c-'0'),c=getchar();
}

long long a,b,k;

int main(){
    scan(a);scan(b);scan(k);
    a*=2;b*=2;
    priority_queue > q;
    q.push(make_pair(-a,0));
    q.push(make_pair(-b-1LL,1));
    for(;k-->1;){
        pair x=q.top();q.pop();
        if(x.second==0){
            x.first-=a;
            q.push(x);
        }else{
            x.first-=b;
            q.push(x);
        }
    }
    
    pair x=q.top();
    puts(x.second?"Aoki":"Takahashi");
    return 0;
}


Problem C - Domino Effect

给你一个r*c的矩阵(r,c<=50),以左上角为(1,1),向下为x增大方向,向右为y增大方向,每个单元里是2种多米诺骨牌:

R:向右倒

C:向下倒

输入中还有一种情况

?:表示不确定,可以是R或C的任意一种(保证输入中不超过10个?)

现在你需要把所有多米诺骨牌推倒。请问,最少推倒次数的期望是多少?

比如,输入

1 2

??

输出1.5000000000000000000

对??,一共4种可能

RR、RC、CR、CC

对RR、RC,推倒全部骨牌,只需要动手1次(推(1,1))

对CR、CC,推倒全部骨牌,必须动手2次

所以,最小推倒次数的期望是1.5。



因为输入中不超过10个?,要枚举的情况也就1024种,所以暴力枚举走起。


对每种恢复的情况,怎么求最小的推倒次数期望呢?

因为骨牌只能向下和向右,不会回头,所以,我们只要找一块不会有任何骨牌可以压到的骨牌去推就行了

比如,上来就先推(1,1),因为(1,1)没有上面的和左边的骨牌了

之后再找一块没有上面和左边的骨牌的去推,贪心推完,就是最少次数。

(代码实现中采用了从第1行扫到最后一行,每行从左向右扫,没倒就推的办法。想一想,为什么这样找到的骨牌一定满足条件?)

最后使用数学期望的定义,算一下,输出,完事。

#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
using namespace std;
typedef long long ll;

int r,c;
char mp[55][55];
bool fall[55][55];

struct Node{
    int x,y;
    Node(){}
    Node(int a,int b):x(a),y(b){}
    void set(char c){
        mp[x][y]=c;
    }
};
vector qmark;

int ans=0;

void makef(int x,int y){
    while(x

Problem D - Balanced Parentheses

现在你有一个长度为n(n<=300000)的,残缺的括号序列(只由' ( ' 和 ' ) '组成),你需要通过插入字符,使得这个残缺的序列变成合法的括号序列

你可以在原始残缺序列的开始、末尾和任意2个字符之间加 ' ( ' 或者 ' ) ' ,一个位置可以插入多次,每个位置有不同的代价。

求变成合法的括号序列需要的最小代价。


比如:输入

4

)(()

1 7 2 8 5

输出:3

在最开头和两个(中间分别插入(和),得到:

 ( ) ( ( )

(加粗的字符为插入的字符)

插入代价为1+2=3,这是最小的方案。


下面留白,这个题有点意思,大家可以思考一下。














做法:

考虑如何进行括号匹配的检查。

从左到右,碰到左括号压栈,碰到右括号出栈

如果需要出栈的时候,栈里没有左括号,那就不是合法序列,直接返回false

如果整个串处理完了,栈里还有左括号,那也不是合法序列,返回false


现在要变成合法序列,就要考虑,这两种返回false的情况都应该避免。

先考虑解决第一种情况。

如果要出栈的时候没有左括号,那就——强行塞给他一个啊!

所以,从左到右,一个右括号找不到匹配的左括号的时候,在这个右括号前面的所有位置里,挑一个代价最小的位置,补上一个左括号。

(for dummies:挑一个代价最小的位置,这件事情怎么做才做的漂亮?

答:你看你现在要从左到右扫过去吧?那我可不可以同期维护一个变量,表示前面的东西的最小值?当我考虑的位置往后移的时候,最新的最小值=min(之前的最小值,新位置的值))


ok,现在考虑解决第二个问题——栈里残留的左括号。

考虑从右往左进行二次检查,

之前我们希望对每个要求出栈的 ) ,有残余的 ( 与之匹配

现在,我们希望对每个 ( ,要求有多余的 ) 与之匹配——而之前第一遍多出来的(是没有的

所以,类似的,从后往前扫描,) 入栈,( 出栈,出栈时没有对应括号的,在之前扫过的位置挑一个代价最小的地方补一个 ) 。

问题解决。

时间复杂度:正着扫一遍,倒着扫一遍,所以是O(n)的。


因为最坏情况下,一个位置的权值有10亿之大,最坏有300000括号要插入,所以,结果需要用64位整型表示。


#include 
#include 
#include 
#include 
#include 
#include 
#include 
using namespace std;
typedef long long ll;

template 
inline void scan(T &ret) {
    char c; ret=0;
    while((c=getchar())<'0'||c>'9');
    while(c>='0'&&c<='9') ret=ret*10+(c-'0'),c=getchar();
}

inline void out(long long x) {
   if(x>9) out(x/10);
   putchar(x%10+'0');
}

ll ans=0;

char str[300005];
int weight[300005];

int main(){
    int n;
    scanf("%d%s",&n,str);
    for(int i=0;i<=n;i++)scan(weight[i]);
    
    {
        int left=0;
        int minv=weight[0];
        for(int i=0;i=0;i--){
            if(str[i]=='(')--left;
            else if(str[i]==')')++left;
            if(left<0){
                ans+=minv;
                left=0;
                str[i]=' ';
            }
            minv=min(minv,weight[i]);
        }
    }
    
    out(ans);
    return 0;
}


你可能感兴趣的:(校招)