GithubHelp home page GithubHelp logo

pat's Introduction

pat's People

Contributors

goby avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar

pat's Issues

1029 Median

水题三连击,主要是理清两个数列的游标增长规则

int main() {
    vector<long> firstArray, secondArray;
    long tmp, cur;
    DRI(N);
    REP(i, N){
        scanf("%ld", &tmp);
        firstArray.push_back(tmp);
    }
    DRI(M);
    REP(i, M){
        scanf("%ld", &tmp);
        secondArray.push_back(tmp);
    }

    tmp = (N + M - 1)/2;
    for (int i = 0, j = 0; tmp >= 0; tmp--) {
        if(j < M && (i == N || firstArray[i] > secondArray[j])) {
            cur = secondArray[j];
            j++;
        }
        else {
            cur = firstArray[i];
            i++;
        }
    }

    printf("%ld", cur);
}

1012 The Best Rank

排名,主要是利用sort方法吧, 当时我怎么用了那么多数组来着,一般用个 vector 加上一个 table[SIZE] 记录对应id在vector中的位置即可(索引)

1026 Table Tennis

又一道恶心的模拟题……比之前的银行排队又难了一点,主要是里头是有VIP桌子。

规则如下:

  1. 普通人先到普通桌,VIP先到VIP桌
  2. 没有VIP排队时,普通人可以使用VIP桌
  3. 如果VIP来了,没有VIP桌,可以到普通桌
#define SIZE 101

#define GETTIME(H, M, S) ((H)*3600+(M)*60+(S))

#define CLOSETIME 21*3600

typedef struct _player {
    int arrriveTime;
    int playTime;
    int isVIP;
} Player;

bool cmp(Player left, Player right){
    return left.arrriveTime < right.arrriveTime;
}
vector<Player> playerList;
int availableTime[SIZE] = {0};
bool table[SIZE] = {0};
int serveCount[SIZE] = {0};

void to_time(int value, int& hh, int& mm, int& ss){
    hh = value / 3600;
    mm = (value % 3600)/60;
    ss = value % 60;
}

void println(int arriveTime, int startTime){
    int hh, mm, ss;
    to_time(arriveTime, hh, mm, ss);
    printf("%02d:%02d:%02d ", hh, mm, ss);
    to_time(startTime, hh, mm, ss);
    printf("%02d:%02d:%02d ", hh, mm, ss);
    printf("%d\n", ((startTime-arriveTime)+30)/60);
}

//  把指定时间内的VIP提前
void reorderPlayerList(int startIndex, int totalPlayer, int beforeTime){
    REPP(i, startIndex+1, totalPlayer){
        if(playerList[i].isVIP && playerList[i].arrriveTime <= beforeTime){
            Player tmp = playerList[i];
            for(int k = i; k> startIndex; k--)
                playerList[k]=playerList[k-1];
            playerList[startIndex]=tmp;
            return;
        }
    }
}

int main() {
    int hh, mm, ss, playTime, vip;
    DRI(N);
    REP(i, N){
        Player p;
        scanf("%d:%d:%d %d %d", &hh, &mm, &ss, &playTime, &vip);
        p.arrriveTime = GETTIME(hh, mm, ss);
        p.playTime=(playTime > 120 ? 120 : playTime) * 60;
        p.isVIP=vip;
        playerList.push_back(p);
    }
    sort(ALL(playerList), cmp);

    DRII(K, M);
    REP(i, M){
        DRI(tmp);
        table[tmp-1] = true;
    }

    REP(i, N){
        if(playerList[i].arrriveTime >= CLOSETIME)
            break;

        int availIndex=-1, vipIndex=-1;
        REP(k, K){
            if(availableTime[k] < playerList[i].arrriveTime){
                availIndex=k;
                break;
            }
        }
        REP(k, K){
            if(table[k] && availableTime[k] < playerList[i].arrriveTime){
                vipIndex=k;
                break;
            }
        }

        // 有空桌
        if(availIndex >= 0){
            if(playerList[i].isVIP && vipIndex >= 0)
                availIndex=vipIndex;
            serveCount[availIndex]++;
            availableTime[availIndex]=playerList[i].arrriveTime+playerList[i].playTime;
            println(playerList[i].arrriveTime, playerList[i].arrriveTime);
        }
        else{ 
            // 没有空桌,寻找最近一张可用桌
            int ealist=CLOSETIME;
            REP(k, K){
                if(availableTime[k] < ealist){
                    ealist=availableTime[k];
                    availIndex=k;
                }
            }
            if(availIndex < 0)
                break;
            // 如果当前为VIP桌,看看有没有要插队的VIP
            if(table[availIndex] && (!playerList[i].isVIP))
                reorderPlayerList(i, N, availableTime[availIndex]);
            serveCount[availIndex]++;
            println(playerList[i].arrriveTime, availableTime[availIndex]);
            availableTime[availIndex]+=playerList[i].playTime;
        }
    }

    printf("%d", serveCount[0]);
    REPP(i, 1, K){
        printf(" %d", serveCount[i]);
    }

    return 0;
}

1013 Battle Over Cities

求图的割点,主要是用DFS求割点

#define SIZE 1001
vector<int> adjs[SIZE];
bool marked[SIZE];

void DFS(int x) {
    int size=adjs[x].size();
    marked[x]=true;

    REP(i,size){
        if(adjs[x][i] != 0 && !marked[adjs[x][i]])
            DFS(adjs[x][i]);
    }
}


int main() {
    DRIII(N,M,K);
    REP(i,M) {
        DRII(v,u);
        adjs[v].push_back(u);
        adjs[u].push_back(v);
    }
    REP(i,K) {
        DRI(city);
        int num=0;
        MS0(marked);
        marked[city] = true;
        REP(i,N+1) {
            if(!marked[i+1]) {
                num++;
                DFS(i+1);
            }
        }
        printf("%d\n", num > 1 ? num-2:0);
    }

    return 0;
}

1031 Hello World for U

水题,主要要清楚U型的排列规则

int main() {
    char arr[81];
    RS(arr);
    int len = LEN(arr);
    int n1 = (len+2)/3 - 1;
    int spacewidth=n1 > 0 ? len-2*n1 - 2 : 0;
    REP(i, n1){
        printf("%c", arr[i]);
        REP(j, spacewidth) printf(" ");
        printf("%c\n", arr[len - 1 - i]);
    }
    REPP(i, n1, len - n1) printf("%c", arr[i]);

    return 0;
}

1023 Have Fun with Numbers

这题弄个int[10]记录数字出现的个数就好了,然后双倍之后再减,判断最后是否都为0就好了。

当时做的时候比较傻。

Source Code

1005 Spell It Right

水题,弄个

char* dict[] = {"zero","one", "two", "three", "four", "five", "six", "seven", "eight", "nine"};

字典就ok了

1021 Deepest Root

一棵树中求树最高的时候的根ID。

基本就是DFS求最深深度,有一种优化思路,就是当某一个节点P的相邻节点如果不在P的最深路径上面,那么这些节点的深度就是Height(P)+1,但是考试时间比较短所以直接暴力了

#define SIZE 10001

vector<int> *adj;
bool visited[SIZE];

int dfs(int start) {
    visited[start] = true;
    int size = adj[start].size();
    int max = 0, ret;
    REP(i, size){
        if(!visited[adj[start][i]]){
            ret = dfs(adj[start][i]);
            if(max < ret)
                max = ret;
        }
    }
    return max + 1;
}

int main() {
    DRI(N);
    adj = new vector<int>[N+1];
    REP(i, N-1){
        DRII(f, t);
        adj[f].push_back(t);
        adj[t].push_back(f);
    }

    int component = 0;
    int max = 0, ret;
    vector<int> result;
    REPP(i, 1, N+1){
        if(!visited[i]){
            component++;
            dfs(i);
        }
    }
    if(component == 1){
        REPP(i, 1, N+1){
            MS0(visited);
            ret = dfs(i);
            if(ret > max) {
                max = ret;
                result.clear();
                result.push_back(i);
            }
            else if(ret == max) {
                result.push_back(i);
            }
        }

        int size = result.size();
        REP(j, size){
            printf("%d\n", result[j]);
        }
    }
    else {
        printf("Error: %d components", component);
    }
    return 0;
}

1007 Maximum Subsequence Sum

就是求最大连续子串之和,顺便把开始结束位置记录一下

当时数据结构的课已经过去4年了,做这个题目搞死我,不然就是个水题而已

要是当时我去考试肯定被搞死……略悲伤

int main()
{
    // max = [sum, start, end]
    int max[3] = {0},sum=0,start=-1,end;
    int n0;    // first input integer
    bool first=true;
    max[0] = -1;
    CASET{
        DRI(num);
        // 截止到当前
        end=num;
        sum += num;
        // 第一个数
        if(first) {n0=start=num;first=false;}
        // 若前面之和作废,重置初始值
        if(!start)start=num;
        // 更新最大值
        if(sum > max[0]){max[0]=sum;max[1]=start;max[2]=end;}
        // 重置和
        if(sum <= 0){sum=0;start=0;}
    }
    if(max[0]<0){max[0]=0;max[1] = n0;max[2]=end;}
    printf("%d %d %d",max[0],max[1],max[2]);
    return 0;
}

1015 Reversible Primes

有点绕的水题

  1. 判断素数
  2. 根据进制翻转数字,在判断素数
bool IsPrime(int x){
    int up=sqrt(x)+1;
    if(x < 2) return false;
    REPP(i,2,up) if(x % i == 0) return false;
    return true;
}

int CalReverse(int x, int radix) {
    int i = 0,result = 0;
    while(x != 0){
        num[i++]=x%radix+'0';
        x = x / radix;
    }
    num[i]=0;
    i=0;
    while(num[i]){
        result *= radix;
        result += num[i]-'0';
        i++;
    }
    return result;
}

int main() {
    int n, radix;
    while(1){
        RI(n);
        if(n<0) break;
        RI(radix);
        if(IsPrime(n) && IsPrime(CalReverse(n, radix)))
            printf("Yes\n");
        else
            printf("No\n");
    }
    return 0;
}

1010 Radix

大坑题,完全没有交代清楚 PAT里超多这种题目...

关系没理清,所以每次遇到这种题目都是N多的判断语句...

  1. 1的N进制都是1,所以设为二进制
  2. 两数字相同则为同进制
  3. 遍历2-36进制是否相同
  4. 大于36之后,则利用二分法搜索结果

二分法子分支的进入也搞了我很久...为了求符合结果的最小值,所以:

  1. start相同则返回
  2. start==end 或者 start 高于值 或者 end 低于值, 返回 0
  3. center相同或者大于取start-center
  4. center小于取center, end
LLONG cal(char* str, LLONG radix)
{
    LLONG a = 0;
    REPC(i,str[i]=='\0'){
        int value = (str[i] >= 'a') ? (str[i]-'a'+10):(str[i]-'0');
        if(value >= radix) return -1;
        a *= radix;
        a += value;
    }
    return a;
}

LLONG bfs(LLONG value, char* target, LLONG start, LLONG end){
    if(start == end) return 0;
    LLONG center = start + (end-start+1) / 2;
    LLONG s = cal(target, start);
    LLONG c = cal(target, center);
    LLONG e = cal(target, end);
    if(e<value || s > value) return 0;
    if(s==value) return start;
    if(center!=end&&c==e)
        return bfs(value, target, start, center);
    if(value==c) return center;
    if(center==end) return 0;

    if(value<c) return bfs(value, target, start, center);
    return bfs(value, target, center, end);
}

int main()
{
    char A[11],B[11],*c,*d;
    LLONG a = 0,result=0;
    RS(A);
    RS(B);
    DRII(tag,radix);
    if(tag==1){
        c=A;d=B;
    }
    else{
        c=B;d=A;
    }
    if(cal(c,37) * cal(d,37)==1) result = 2;
    else if(strcmp(c,d)==0) result=radix;
    else if((a=cal(c,radix))>=0){
        REP(i,37){
            if(cal(d,i)==a) {result=i;break;}
        }
        if(!result) result=bfs(a,d,2,a>36?a:36);
    }
    if(result)printf("%lld",result);
    else printf("Impossible");
    return 0;
}

1009 Product of Polynomials

水题

幂最大才1000,乘的话只需要开个2_1000的空间记录每个幂上面的系数即可。系数计算就是 N_M的复杂度了。

1003 Emergency

妈蛋题目看错结果这题纠结了1个月

本题重点在于Dijkstra,以及全部最短路径保存和最后DFS(计算最短路径数+获得最优解)

1024 Palindromic Number

这题的主要难度在于K 最大可能到100,N最多有10位,如果按最大可能,最后可能有110位,所以需要用字符处理数字。

PAT这是第二道用字符处理数字的题目了。

1019 General Palindromic Number

对于进制考察比较全面的题目,判断用K进制表示翻转之后与原来的是否一致, 翻转直接用循环即可, 输出就需要借助递归完成了。

void print(int n, int radix){
    if (n < radix) {
        printf("%d", n);
        return;
    }
    print(n/radix, radix);
    printf(" %d", n % radix);
}

int main() {
    DRII(N, radix);

    int res=0, ori=N;
    while (ori) {
        res *= radix;
        res += ori % radix;
        ori /= radix;
    }
    printf("%s\n", res==N ? "Yes" : "No");
    print(N, radix);

    return 0;
}

1028 List Sorting

又一道水题,主要是认真看排列规则就行了

typedef struct {
    int id;
    char name[10];
    int score;
} Student;

template <int i>
bool cmp(Student left, Student right){
    if(i == 0)
        return left.id < right.id;
    if(i == 1) {
        int res = strcmp(left.name, right.name);
        if(res == 0)
            return left.id < right.id;
        return res < 0;
    }
    else {
        if(left.score == right.score)
            return left.id < right.id;
        return left.score < right.score;
    }
}

vector<Student> students;

int main() {
    DRII(N, C);
    REP(i, N){
        Student s;
        cin >> s.id >> s.name >> s.score;
        students.push_back(s);
    }
    switch (C) {
        case 1:
            sort(ALL(students),cmp<0>);
            break;
        case 2:
            sort(ALL(students),cmp<1>);
            break;
        case 3:
            sort(ALL(students),cmp<2>);
            break;
        default:
            break;
    }

    for (auto it = students.begin(); it != students.end(); it++)
        printf("%06d %s %d\n", it->id, it->name, it->score);
}

1022 Digital Library

这题因为没主意看题意结果提交好几次错误

这题应该是比较简单,只是比较繁复,可能是数量比较少+STL的缘故把。

1018 Public Bike Management

just now
7 days ago ...
a month ago ...

终于AC了……这种题目真的是有一点没想到就基本很难想得到...

代码也改了好多次,改得乱七八糟的。

  1. 最短路径 -> Dijkstra
  2. 最短基础上要求送出的最少
  3. 送出最少的基础上收回最少

原来一直没想明白,只是觉得要么只送出要么只收回,后来才恍然大悟发现不能走回头路!!!!!!!!!就是如果第一个站缺10辆,不管后来的多出了多少辆,肯定要先送出10辆...

思路理清了就是 Dijsktra + DFS 经典组合

#define SIZE 501

int dd[SIZE][SIZE];      // 距离关系
int cc[SIZE];          // 车辆数量
vector<int> pred[SIZE];    // 前驱点列表
vector<int> dist;   
bool visited[SIZE];
int route[SIZE], tmpRoute[SIZE];     // 路径记录

int length = SIZE;       // 路径长度
int Cmax;           // 每个站最大容量
int sendTo=INT_MAX, takeBack=INT_MAX;             // 送出和送回的数量

void dfs(int start,int end, int level){
    tmpRoute[level] = end;
    if(start == end){
        // 一堆涂改变量
        int m = 0, tmp = 0, perfect = Cmax / 2, st, tb, totalCount = 0;
        RREP(i,level){
            totalCount += cc[tmpRoute[i]];
            // 从开始获取缺少的车辆,发现缺车辆,记录并重置tmp
            tmp += cc[tmpRoute[i]] - perfect;
            if(tmp < 0) { m -= tmp;tmp = 0; }
        }
        // 送出
        st = m; 
        // 送回
        tb = totalCount + st - level * (Cmax/2);

        if(st < sendTo || (st == sendTo && tb < takeBack)){
            sendTo = st;
            takeBack = tb;
            memcpy(route, tmpRoute, level*sizeof(int));
            length = level;
        }

        return;
    }
    int size = pred[end].size();
    REP(i, size){
        dfs(start, pred[end][i], level+1);
    }
}

int main()
{
    int c0, c1, d, tmp;
    RI(Cmax);
    DRI(N);
    DRII(target, M);
    MS1(dd);
    MS1(cc);
    MS1(route);
    dist.assign(N + 1, INT_MAX);
    cc[0]=0;
    REP(i, N){
        RI(tmp);
        cc[i+1]=tmp;
    }
    REP(i, M){
        RIII(c0, c1, d);
        dd[c0][c1]=dd[c1][c0]=d;
    }
    dist[0] = 0;
    while (true) {
        int  u = -1;
        int m = INT_MAX;
        REP(i, N+1){
            if(!visited[i] && m > dist[i]){
                u = i;
                m = dist[i];
            }
        }
        if(u == -1) break;
        visited[u] = true;
        REP(i, N+1){
            if(i != u && dd[i][u] >= 0){
                long len = dd[i][u];
                len += dist[u];
                if(len < dist[i]){
                    dist[i] = len;
                    pred[i].clear();
                    pred[i].push_back(u);
                }
                else if(len == dist[i]){
                    pred[i].push_back(u);
                }
            }
        }
    }

    dfs(0, target, 0);

    printf("%d 0", sendTo);
    while(length--){
        printf("->%d", route[length]);
    }
    printf(" %d", takeBack);

    return 0;
}

1033 To Fill or Not to Fill

AC了饿

想法是这样纯贪心策略:
车加满油最多走 MaxRunning 的路,那么:

到第K个站的时候( K = 0, 1, 2, ... , N - 1) :

  1. 邮箱中还有 Available 的油
  2. 需要往邮箱添加 Refuel 量的油走到下一个站
  3. 取下一个站 NextStation
  4. 逐个往后 MaxRunning 和 目标里程 范围内寻找这个 NextStation
  5. 如果找到一个站油价P小于当前价格:直接将 NextStation 置为 P, 并且把油加到刚好开到这个站
  6. 否则,如果找到大于等于当前价格的最低价格P: NextStation = P,如果目标在可达范围之类,加到可达目标即可,否则加满油
  7. 否则,如果找不到站,则可能 1) 开不到终点, 2) 终点在可达范围之内

差不多就这样,搞死我了

struct station{
    double price;
    double location;
};

bool cmp(station left, station right){
    return left.location < right.location;
}

int main() {
    vector<station> stations;
    double Cmax, D, Davg, N;
    station s;
    scanf("%lf%lf%lf%lf", &Cmax, &D, &Davg, &N);
    REP(i, N){
        scanf("%lf%lf", &s.price, &s.location);
        stations.push_back(s);
    }

    sort(ALL(stations), cmp);
    int cur = 0;
    double runDis = Cmax * Davg, total = 0, amount = 0, available = 0;

    while (cur < N) {
        // 找到目标或者无法到达
        if(total >= D || total < stations[cur].location) break;
        // 寻找下一个站点
        int min = -1;
        for(int i = cur + 1;i < N
            && stations[i].location - stations[cur].location <= runDis; i++) {
            if(min == -1 || stations[i].price < stations[min].price)
                min = i;
            if(stations[min].price < stations[cur].price)
                break;
        }

        double needAdd = 0, cost = 0;

        if(min == -1) {                         // 1).  找不到
            if(total + runDis > D)
                cost = (D - total) / Davg;      // 目标在可达范围内
            else
                cost = Cmax;                    // 可达范围外

            needAdd = cost - available;
            total += cost * Davg;
            min = cur + 1;
        }
        else if(stations[min].location >= D){   // 2). 在目标里程之外,开到目标即可
            cost = (D - total) / Davg;
            needAdd = cost - available;
            total = D;
        }
        else if(stations[min].price > stations[cur].price) { // 3). 比当前价格高,经过加尽量少得油
            if(total + runDis >= D) {           // 目标可达,直接行驶到目标
                cost = (D - total) / Davg;
                needAdd = cost - available;
                total = D;
            }
            else {                              // 否则加满油
                cost = (stations[min].location - total) / Davg;
                needAdd = Cmax - available;
                total = stations[min].location;
            }
        }
        else {   // 4). 比当前小,加到刚好开到最小的站即可(分支2排除这里头直接到达目标的可能)
            cost = (stations[min].location - total) / Davg;
            needAdd = cost - available;
            total = stations[min].location;
        }
        available = available + needAdd - cost;
        amount += needAdd * stations[cur].price;
        cur = min;
    }

    if(total < D) printf("The maximum travel distance = %.2lf", total);
    else printf("%.2lf", amount);

    return 0;
}

1030 Travel Plan

双重权值的Dijkstra题目 感觉这期题目难度降了0.5-1.0

#define SIZE 501

int dd[SIZE][SIZE];
int cc[SIZE][SIZE];
int pred[SIZE];
vector<int> dist;
vector<long> cost;
bool visited[SIZE];
int route[SIZE];

int max = 0;

int main() {
    int c0, c1, d, c;
    DRII(N, M);
    DRII(start, end);
    MS1(dd);
    MS1(cc);
    MS1(route);
    MS1(pred);
    dist.assign(N, INT_MAX);
    cost.assign(N, INT_MAX);

    REP(i, M){
        RII(c0, c1);
        RII(d, c);
        dd[c0][c1]=dd[c1][c0]=d;
        cc[c0][c1]=cc[c1][c0]=c;
    }
    dist[start] = 0;
    cost[start] = 0;
    while (true) {
        int  u = -1;
        int m = INT_MAX;
        REP(i, N){
            if(!visited[i] && m > dist[i]){
                u = i;
                m = dist[i];
            }
        }
        if(u == -1) break;
        visited[u] = true;
        REP(i, N){
            if(i != u && dd[i][u] >= 0){
                long len = dd[i][u];
                len += dist[u];
                long cst = cc[i][u];
                cst += cost[u];
                if(len < dist[i]){
                    dist[i] = len;
                    pred[i] = u;
                    cost[i] = cst;
                }
                else if(len == dist[i]){
                    if(cst < cost[i]){
                        cost[i]=cst;
                        pred[i] = u;
                    }
                }
            }
        }
    }

    int len = 0, cur = pred[end];
    while (cur != start) {
        route[len++]=cur;
        cur=pred[cur];
    }
    printf("%d", start);
    while (len) {
        printf(" %d", route[--len]);
    }
    printf(" %d", end);
    printf(" %d %d", dist[end], cost[end]);

    return 0;
}

1020 Tree Traversals

根据后序遍历Post[]、中序遍历输出前序In[],原来的办法是想能不能直接比较Post、In两个数组得到前序,发现不行。只好乖乖地还原树了。

根据中序和后序遍历的特点,后序遍历的话父节点总在最后面的,对于中序遍历,则父节点在中间;因此对于:

Post[k], Post[k+1], Post[k+2], ... Post[k+N]
In[j], In[j+1], In[j+2] ... In[j+N]

当前的子树的根节点为Post[k+N], 假设In[j+p] == Post[k+N], 那么当前树的左子树为:Post[k], Post[k+1] ... Post[k+p-1] 和 In[j], In[j+1] ... In[j+p-1];
右子树为: Post[k+p], Post[k+p+1] ... Post[k+N-1] 和 In[j+p+1], In[j+p+2], ... , In[j+N]。

所以下一次迭代为:
Left: k = k, j = j, len = p - 1
Right: k = k+p, j = j + p + 1, len = N - p - 1

vector<int> post;
vector<int> in;

typedef struct _node node;
struct _node {
    int value;
    node* left;
    node* right;
};
queue<node*> result;

/// ps: postorder starting index;
/// is: inorder starting index
node* dfs(int ps, int is, int len){
    int value = post[ps + len -1];
    int pivot=is;
    node * n = new node;
    n->left=n->right=NULL;
    n->value = value;
    REPP(i, is, is+len){
        if(in[i]==value){
            pivot=i-is;
            break;
        }
    }
    if(pivot > 0) n->left = dfs(ps, is, pivot);
    if(len > pivot+1) n->right = dfs(ps+pivot, pivot+is+1 , len - pivot - 1);
    return n;
}

int main()
{
    DRI(N);
    REP(i,N){DRI(x);post.push_back(x);}
    REP(i,N){DRI(x);in.push_back(x);}
    node *tree = dfs(0,0, N);
    bool flag=true;
    result.push(tree);
    while (!result.empty()) {
        node* value=result.front();
        result.pop();
        if(flag) {printf("%d", value->value); flag=false;}
        else printf(" %d", value->value);
        if(value->left) result.push(value->left);
        if(value->right) result.push(value->right);
    }
    return 0;
}

1016 Phone Bills

给出一堆电话拨打记录,求订单

  1. 按名字和时间排序
  2. 根据题意,每个人只能同时拨打给一个人,所以打电话和挂电话必定在前后相邻两个记录中
// 价格
int rate[24];
// 通话记录
typedef struct _record{
    char name[21];
    int time[3];
    bool flag;
}record;

bool cmp(record l, record r){
    int value = strcmp(l.name, r.name);
    if(value==0)
        return l.time[0]*24*60+l.time[1]*60+l.time[2] < r.time[0]*24*60+r.time[1]*60+r.time[2];
    return value < 0;
}

// 计算通话费用
int cost(record &re){
    int result = 0;
    REP(i, re.time[1]){
        result += rate[i]*60;
    }
    result += rate[re.time[1]]*re.time[2];
    REP(i, 24){
        result += (rate[i]*60)*(re.time[0]-1);
    }
    return result;
}

int diff(record &l, record &r){
    return l.time[0]*24*60+l.time[1]*60+l.time[2] - (r.time[0]*24*60+r.time[1]*60+r.time[2]);
}

int main()
{
    int  month;
    float sum = 0;
    char prename[9]={0};
    char hang[9];
    vector<record> records;
    REP(i,24) RI(rate[i]);
    CASET{
        record *r = new record;
        RS(r->name);
        scanf("%d:%d:%d:%d", &month, r->time, r->time+1, r->time+2);
        RS(hang);
        r->flag = hang[1]=='n';
        records.push_back(*r);
    }
    sort(ALL(records), cmp);
    int size=records.size();
    REP(i, size-1){
        record on =records[i], off=records[i+1];
        if(on.flag && !off.flag && (strcmp(on.name, off.name)==0)){
            if(strcmp(prename, on.name)!=0){
                strcpy(prename, on.name);
                if(sum) printf("Total amount: $%.2f\n", sum);
                printf("%s %02d\n", prename, month);
                sum = 0;
            }
            float tmp = (cost(off)-cost(on))/100.0;
            sum+=tmp;
            printf("%02d:%02d:%02d %02d:%02d:%02d %d $%.2f\n", on.time[0],on.time[1],on.time[2],
                off.time[0],off.time[1],off.time[2],diff(off, on), tmp);
        }
    }
    if(sum) printf("Total amount: $%.2f\n", sum);
    return 0;
}

1014 Waiting in Line

模拟题, 大坑题

模拟题完全不行啊怎么办啊,坑题表现在一些结果判定上没有写清楚

我这里用了数组来表示队列,用一个游标指代当前队列的头

模拟的时候根据时间来的

#define SIZE 1001
#define TOTALTIME 541
int win[20][10];        // 窗口队列
int pw[20];
int tt[20];
int dealTime[SIZE];
int main()
{
    DRII(N,M);
    DRII(K,Q);

    int p=0, max=0;
    int cost[SIZE];
    int query[SIZE];
    // 此处记录最大处理时间
    REP(i, K) {RI(cost[i]); if(cost[i] > max) max= cost[i];}
    REP(i, Q) RI(query[i]);
    MS0(pw);
    MS0(tt);
    MS1(dealTime);
    // 先将N个人入列
    REP(i,N*M){
        if(i>K) break;
        win[i%N][i/N]=i;
        if(!tt[i%N]) tt[i%N] = cost[i];
        p=i+1;
    }
    // 此处是按照时间来模拟的,轮询
    REP(i, TOTALTIME+max){
        REP(j, N){
            // tt[] 为窗口的处理结束时间, pw[]为窗口指针指向第几个处理者
            // dealTime为处理时间
            if(tt[j] == i &&  win[j][pw[j]] >= 0 && dealTime[win[j][pw[j]]] < 0){
                dealTime[win[j][pw[j]]]=i-cost[win[j][pw[j]]];//save deal time
                if(p < K) win[j][pw[j]]=p++;
                else win[j][pw[j]]=-1;    //表示没有人了
                pw[j]++;//deal nxt one & add time to observe
                pw[j]=pw[j]%M;
                tt[j]+=cost[win[j][pw[j]]];
            }
        }
    }

    REP(i, Q){
        if(dealTime[query[i]-1] >= 0 && dealTime[query[i]-1] < TOTALTIME - 1){
            int t=dealTime[query[i]-1]+cost[query[i]-1]; 
            printf("%02d:%02d\n",(t/60+8),t%60);
        }
        else printf("Sorry\n");
    }

    return 0;
}

1017 Queueing at Bank

又一道模拟题

之前一道银行排队的变种,但这里每个窗口的Cache只有1,所以应该相对来说简单一些。这次以顾客的身份来解题。

  1. 将顾客按先来后到顺序排列 Customers[]
  2. 用一个优先队列存储每个窗口的可用时间 WinQueue
  3. 遍历Customers
  4. 从WinQueue取最小值Win,若当前Customer比WinQueue来得早,Win加上处理时间,重新放回队列,否则将Win设置为Customer到达时间,再加上处理时间,放回队列
  5. 如果Customers不为空,返回2
// Customer
typedef struct _t{
    int arrive;
    int process;
}cst;

bool cmp(cst l, cst r) {
    return l.arrive < r.arrive;
}

const int ftime=540*60+1;
int main() {
    DRII(N,K);
    int p=0, total = 0;
    vector<cst> all;
    REP(i, N){
        int h,m,s;
        scanf("%d:%d:%d", &h, &m, &s);
        cst *t = new cst;
        t->arrive =(h - 8)*3600+m*60+s;
        DRI(process);
        t->process=process*60;
        all.push_back(*t);
    }
    sort(ALL(all), cmp);
    priority_queue<int, vector<int>,greater<int>> pq;
    REP(i, K) pq.push(0);
    while(p < N && all[p].arrive < ftime){
        int top = pq.top();
        pq.pop();
        if(top < all[p].arrive) top = all[p].arrive;/*IMPORTANT*/
        total +=  top - all[p].arrive;
        top += all[p].process;
        pq.push(top);
        p++;
    }
    if(p) printf("%.1f", total * 1.0 / 60 / p);
    else printf("0.0");
    return 0;
}

1025 PAT Ranking

比较简单的题目,sort搞定。坑主要在排名规则。

1027 Colors in Mars

大水题...

char dict[]={'0','1','2','3','4','5','6','7','8','9','A','B','C'};

int main() {
    DRIII(r,g,b);
    printf("#");
    printf("%c%c", dict[r/13], dict[r%13]);
    printf("%c%c", dict[g/13], dict[g%13]);
    printf("%c%c", dict[b/13], dict[b%13]);

    return 0;
}

1032 Sharing

这题和寻找树中两个节点的共同祖先是一个道理,而且更简单一些。

简单来说就是找到完整地两条链。不知之前怎么做的还OT过几次。

#define SIZE 100000

int tnext[SIZE];

int main() {
    DRIII(fst, snd,N);
    int cur, nxt;
    char c;
    MS1(tnext);
    REP(i, N){
        scanf("%d %c %d", &cur, &c, &nxt);
        tnext[cur] = nxt;
    }

    int len1 = 0, len2 = 0;
    cur = fst;
    while(cur >= 0){
        cur = tnext[cur];
        len1++;
    }
    cur = snd;
    while(cur >= 0){
        cur = tnext[cur];
        len2++;
    }

    if(len1 > len2){
        while(len1 != len2){
            fst = tnext[fst];
            len1--;
        }
    }
    else if(len1 < len2){
        while(len1 != len2){
            snd = tnext[snd];
            len2--;
        }
    }

    while (fst != snd) {
        snd = tnext[snd];
        fst = tnext[fst];
    }
    if(fst >= 0) printf("%05d", fst);
    else printf("%d", fst);

    return 0;
}

1004 Counting Leaves

一看题目是N < 100感觉直接暴力申请个100*100的关系矩阵。

数树叶,差不多就是BFS,我BFS一般都用一个Queue搞定,结果上次参加微策略笔试,这题估计我用一个Queue被改卷老师鄙视了……没办法,这么非主流,早知道用两个Queue了。

根据输入, ParentID ChildrenNum ChildID ChildID .. ChildID, 也就是说,ParentID 未出现过的就是叶子节点,所以弄了个数组 nonleave[] 保存非子节点,减少遍历次数。

int main()
{
    // 前四个为涂改变量,最后为叶子总数
    int father,childnum, child, levelcount=0, total=0;
    queue<int> qq;              // BFS 
    bool isdescendant[SIZE];    // 是否为先祖
    bool nonleave[SIZE];        // 是否有后代
    bool first=true;
    MS0(relative);
    MS0(nonleave);
    MS0(isdescendant);
    DRII(N,M);
    REP(i, M){
        RII(father, childnum);
        nonleave[father]=true;
        REP(j, childnum){
            RI(child);
            relative[father][child]=true;
            isdescendant[child]=true;
        }
    }
    total = N - M;
    // BFS开始,将所有先祖扔进去
    REP(i, N){
        if(!isdescendant[i+1]){
            qq.push(i+1);
            if(!nonleave[i+1])
                levelcount++;
        }
    }
    // 在每一层ID之间添加负数的叶子树作为分隔符
    qq.push(-levelcount);
    levelcount=0;
    while (!qq.empty() && total) {
        int cur=qq.front();
        qq.pop();
        // 遍历查找后代节点
        if(cur > 0 && nonleave[cur]){
            REP(i, N){
                if(relative[cur][i+1]) {
                    qq.push(i+1);
                    if(!nonleave[i+1])
                        levelcount++;
                }
            }
        }
        else if(cur <= 0){
            // 一层结束输出个数
            qq.push(-levelcount);
            total += cur;
            if(!first) printf(" %d", -cur);
            else {printf("%d", -cur);first=false;}
            levelcount=0;
        }
    }

    return 0;
}

1034 Head of a Gang

没做二连击

考试前夕试着搞定这道题

发现是图,可能需要符号表,就用了个 char[] --> int, vector 和 int[] 搞定对应关系,接下来都是对映射之后的数字进行计算。

基本思路就是:从图中得到连通分量N,从中挑选出权值大于K的子图, 计算其中权重最高的节点和节点个数,并对结果进行排序。

第一次提交获得了 1WA 1SF的结果,隐藏的坑是同一个权值输入时可以分次输入, 再提交WA不见了, SF依旧在,不知道是哪个下标越界了。

const int SIZE = 26 * 26 * 26 + 1;

int SymbolTable[SIZE];
int relation[1001][1001];
int gangCal[1001];
bool marked[1001];
vector<int> Symbol;
int memberCount;
int gangAmount;

int str2i(char str[]){
    int result = 0;
    for(int i = 0; i < 3; i++){
        result *= 26;
        result += str[i] - 'A';
    }
    return result;
}

void dfs(int n){
    marked[n] = true;
    REP(i, memberCount){
        if(relation[n][i]){
            gangCal[n] += relation[n][i];
            gangCal[i] += relation[n][i];
            gangAmount += relation[n][i];
            if(!marked[i])
                dfs(i);
        }
    }
}

/// 结果排序用
bool cmp(const pair<int, int>& left, const pair<int, int>& right){
    return  Symbol[left.first] < Symbol[right.first];
}

int main() {
    char nameA[4], nameB[4];
    int talktime, tmp, indexA, indexB;
    vector<pair<int, int>> result;
    DRII(N, K);
    MS1(SymbolTable);
    MS0(relation);
    while (N--) {
        scanf("%s %s %d", nameA, nameB, &talktime);
        indexA = SymbolTable[str2i(nameA)];
        indexB = SymbolTable[str2i(nameB)];
        if(indexA < 0) {
            tmp = str2i(nameA);
            indexA = Symbol.size();
            SymbolTable[str2i(nameA)]=indexA;
            Symbol.push_back(tmp);
        }
        if(indexB < 0) {
            tmp = str2i(nameB);
            indexB = Symbol.size();
            SymbolTable[str2i(nameB)]=indexB;
            Symbol.push_back(tmp);
        }

        relation[indexA][indexB] += talktime;
    }
    memberCount = Symbol.size();
    MS0(marked);
    REP(i, memberCount){
        if(!marked[i]){
            gangAmount = 0;
            MS0(gangCal);
            dfs(i);
            if(gangAmount > K){
                int cnt = 0, maxindex = i;
                REP(j, memberCount){
                    if(gangCal[j]){
                        cnt++;
                        if(gangCal[j] > gangCal[maxindex])
                            maxindex = j;
                    }
                }
                if(cnt > 2){
                    result.push_back(MP(maxindex, cnt));
                }
            }
        }
    }

    sort(ALL(result), cmp);
    int size = result.size();
    printf("%d\n", size);
    REP(i, size){
        int value = Symbol[result[i].first];
        nameA[0] = value / (26 * 26) + 'A';
        nameA[1] = value / 26 % 26 + 'A';
        nameA[2] = value % 26 + 'A';
        nameA[3] = 0;
        printf("%s %d\n",nameA, result[i].second);
    }

    return 0;
}

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.