zoukankan      html  css  js  c++  java
  • 20180922北京网络赛题解

    20180922北京网络赛题解

    A.Saving Tang Monk II

    MEANING

    (n imes m)的网格图,可以向四个方向移动,移动一格耗时1秒,毒气室额外花费1秒,S表示起点,T表示终点,#表示毒气室,拥有氧气瓶才能进入,且消耗一个氧气瓶,每次进入B获得一个氧气瓶,最多同时携带5瓶氧气瓶,进入P获得一个加速,使消耗的时间减少1秒。.表示空的房间。问从S到T最少耗时。

    SOLUTION

    优先队列BFS,耗时少的点优先。vis[x][y][k]表示在(x,y)有k个氧气瓶,每个状态只访问一次。

    CODE

    #include<bits/stdc++.h>
    using namespace std;
    const int MAXN = 105;
    const int dirx[] = {1,-1,0,0};
    const int diry[] = {0,0,1,-1};
    char mapp[MAXN][MAXN];
    bool vis[MAXN][MAXN][6];
    int n,m;
    struct node{
        int x,y,step,oxg;
    };
    bool operator<(node a,node b){
        return a.step>b.step;
    }
    int bfs(node st,node et){
        priority_queue<node> q;
        memset(vis,0,sizeof vis);
        q.push(st);
        vis[st.x][st.y][st.oxg] = 1;
        while(q.size()){
            node cur = q.top();
            if(cur.x==et.x&&cur.y==et.y)return cur.step;
            q.pop();
            for(int i=0;i<4;i++){
                int xx = cur.x+dirx[i],yy = cur.y+diry[i],oo = cur.oxg,ss = cur.step;
                if(xx<0||xx>=n||yy<0||yy>=m)continue;
                if(oo==0&&mapp[xx][yy]=='#')continue;
                if(mapp[xx][yy]=='#')oo--,ss++;
                if(mapp[xx][yy]=='B')oo = min(oo+1,5);
                if(vis[xx][yy][oo])continue;
                vis[xx][yy][oo] = 1;
                if(mapp[xx][yy]=='P')q.push({xx,yy,ss,oo});
                else q.push({xx,yy,ss+1,oo});
            }
        }
        return -1;
    }
    
    int main() {
        while(scanf("%d%d",&n,&m)&&n){
            for(int i=0;i<n;i++){
                scanf("%s",mapp[i]);
            }
            node st,et;
            for(int i=0;i<n;i++){
                for(int j=0;j<m;j++){
                    if(mapp[i][j]=='S'){
                        st={i,j,0,0};
                    }
                    if(mapp[i][j]=='T'){
                        et={i,j,0,0};
                    }
                }
            }
            cout<<bfs(st,et)<<endl;
        }
        return 0;
    }
    

    B.Tomb Raider

    MEANING

    n个字符串,每个字符串是个环,可以自己选起点,输出字典序最小的LCS。

    CODE

    数据很小,暴力
    队友代码

    #include <stdio.h>
    #include <time.h>
    #include <algorithm>
    #include <cstring>
    #include <stack>
    #include <queue>
    #include <string>
    #include <iostream>
    #include <set>
    
    using namespace std;
    typedef long long ll;
    const int maxn = 2000005;
    
    struct SSAM {
        int next[50][26];
        int len;
        set<int>cp[26];
        int find(int p,int ch){
            set<int>::iterator  it = cp[ch].upper_bound(p);
            if (it==cp[ch].end()) return -1;
            else return *it;
        }
        void build(char s[]){
            for (int i=0;i<26;i++) cp[i].clear();
            len = strlen(s);
            for (int i=0;i<len;i++){
                cp[s[i]-'a'].insert(i+1);
                cp[s[i]-'a'].insert(i+len+1);
            }
            for (int i=0;i<=2*len;i++){
                for (int j=0;j<26;j++){
                    next[i][j] = find(i,j);
                }
            }
        }
        bool check(char s[]){
            int le = strlen(s);
            for (int i=0;i<len;i++){
                int j = i;
                for (int k=0; k<le;k++ ) {
                    j = next[j][s[k]-'a'];
                    if ( j==-1 || j> i+len ) break;
                   // printf("j=%d
    ",j);
                }
                if ( j!=-1 && j <= i+len) return true;
            }
            return false;
        }
        void show(){
            for (int i=0;i<=2*len;i++){
                for (int j=0;j<26;j++){
                    printf("%d ",next[i][j]);
                }printf("
    ");
            }
            printf("
    ");
        }
    }ssam[20];
    ll n;
    char str[50][20];
    
    char tmp[50];
    
    string  solve(){
        int len = strlen(str[1]);
        string ans = "";
        for (int i=1;i<=(1<<len)-1;i++){
            int k=0;
            for (int j=0;j<len;j++) {
                if (i & (1 << j)) tmp[k++] = str[1][j];
            }
            tmp[k]='';
            for (int qwe=0;qwe<k;qwe++) {
                int ff = 1;
                for (int l = 2; l <= n; l++) {
                    if (!ssam[l].check(tmp)) {
                        ff = 0;
                        break;
                    }
                }
                if (ff == 1) {
                    string tt = tmp;
                    if (tt.length() > ans.length()) {
                        ans = tt;
                    } else if (tt.length() == ans.length()) {
                        if (tt < ans) {
                            ans = tt;
                        }
                    }
                }
                char rty = tmp[0];
                for (int asd=1;asd<k;asd++) tmp[asd-1] = tmp[asd];
                tmp[k-1] = rty;
            }
        }
        return ans;
    }
    
    int main() {
        while (scanf("%lld", &n) != EOF) {
            for (int i = 1; i <= n; i++) {
                scanf("%s", str[i]);
                ssam[i].build(str[i]);
            }
            string ans = solve();
            if (ans == "") {
                printf("0
    ");
            } else {
                printf("%s
    ", ans.c_str());
            }
        }
        return 0;
    }
    

    C.Cheat

    MEANING

    四个人打一副牌,先出完所有牌的player获胜。游戏的规则是,四个人按顺时针轮流出牌,每次出牌时将牌反置,并声明自己所出的牌均为某一点数(RANK)。其余三人依次决定是否质疑。如果选择质疑,翻开牌,如果与声明一致,质疑者将牌桌所有牌收回手中,反之出牌者将所有牌收回手中。如果没人质疑,牌将留在桌上。每个人声明的RANK从A开始,后一人声明的RANK必须且只能比前一人声明的大一级,特别的,K之后为A,如此循环。
    这四个人每个都有自己的出牌策略和质疑策略。
    player1:出牌策略:如果拥有当前必须声明的RANK,打出一张。否则不得不lie,将一张手中RANK的字典序最小的牌打出,并声明为当前RANK。质疑策略:当自己是下一个出牌者,且不得不lie时,质疑之。或者当前出牌者声明的RANK有p张牌,自己手中有q张时,且p+q>4,质疑之。
    player2:出牌策略:如果拥有当前必须声明的RANK,打出该RANK的全部牌,否则不得不lie,将一张手中RANK的字典序最小的牌打出,并声明为当前RANK。质疑策略:当且仅当自己是下一个出牌者,且不得不lie时,质疑之。
    player3:出牌策略:如果拥有当前必须声明的RANK,打出该RANK的全部牌,否则不得不lie,打出数量最小的某一RANK的全部牌,如果有多种,打出RANK的字典序最小的,并声明为当前RANK。质疑策略:当且仅当自己拥有出牌者所声明的RANK的全部4张牌时,质疑之。
    player4:出牌策略:如果拥有当前必须声明的RANK且有3张或者4张时,打出该RANK的全部牌。否则除了打出该RANK的全部牌(如果有的话),额外加上一张RANK的字典序最小的牌(如果有的话)。质疑策略:当且仅当出牌者没有手牌时,质疑之。

    SOLUTION

    按题意模拟。
    有两个坑。
    一是牌的RANK字典序和RANK不一样,容易忽略J<K<Q。
    二是player4需要出的牌少于三张时,而又无其它RANK的牌时,此时说的是真话。

    CODE

    #include<bits/stdc++.h>
    using namespace std;
    
    int Rank[] = {9, 1, 2, 3, 4, 5, 6, 7, 8, 0, 10, 12, 11}; //rank
    
    int hand[5][14];//lex
    int tran(char s[]) { // char[] to number
        if(strcmp(s, "A") == 0)return 9;
        if(strcmp(s, "J") == 0)return 10;
        if(strcmp(s, "Q") == 0)return 12;
        if(strcmp(s, "K") == 0)return 11;
        if(strcmp(s, "10") == 0)return 0;
        return s[0] - '0' - 1;
    }
    void NeTran(int num,char s[]){
        if(num==9)strcpy(s,"A");
        else if(num==10)strcpy(s,"J");
        else if(num==12)strcpy(s,"Q");
        else if(num==11)strcpy(s,"K");
        else if(num==0)strcpy(s,"10");
        else{
            s[0] = num+1+'0';
            s[1] = '';
        }
    }
    
    bool check(int player) {
        for(int i = 0; i < 13; i++)if(hand[player][i])return false;
        return true;
    }
    
    int cnt;
    int roundHolder, requireRank;
    int cardNum;
    bool state;
    int realcard[15];
    
    void putDown(int player) {
        memset(realcard,0,sizeof realcard);
        cardNum = 0;
        if(player == 1) {
            if(hand[player][requireRank]) {
                hand[player][requireRank]--;
                realcard[requireRank]++;
                cardNum = 1;
                state = 1;
            } else {
                for(int i = 0; i < 13; i++) {
                    if(hand[player][i]) {
                        hand[player][i]--;
                        realcard[i]++;
                        cardNum = 1;
                        break;
                    }
                }
                state = 0;
            }
        }
        else if(player == 2) {
            if(hand[player][requireRank]) {
                realcard[requireRank] = hand[player][requireRank];
                cardNum = hand[player][requireRank];
                hand[player][requireRank] = 0;
                state = 1;
            } else {
                for(int i = 0; i < 13; i++) {
                    if(hand[player][i]) {
                        hand[player][i]--;
                        realcard[i]++;
                        cardNum = 1;
                        break;
                    }
                }
                state = 0;
            }
        }
        else if(player == 3) {
            if(hand[player][requireRank]) {
                realcard[requireRank] = hand[player][requireRank];
                cardNum = hand[player][requireRank];
                hand[player][requireRank] = 0;
                state = 1;
            } else {
                int tot = -1;
                for(int i = 0; i < 13; i++) {
                    if(hand[player][i] && (tot==-1||hand[player][i]<hand[player][tot]))tot = i;
                }
                realcard[tot] = hand[player][tot];
                cardNum = hand[player][tot];
                hand[player][tot] = 0;
                state = 0;
            }
        }
        else  {
            if(hand[player][requireRank] == 3 || hand[player][requireRank] == 4) {
                realcard[requireRank] = hand[player][requireRank];
                cardNum = hand[player][requireRank];
                hand[player][requireRank] = 0;
                state = 1;
            } else {
                realcard[requireRank] = hand[player][requireRank];
                cardNum = hand[player][requireRank];
                hand[player][requireRank] = 0;
                state = 1;
                for(int i = 0; i < 13; i++) {
                    if(hand[player][i]) {
                        hand[player][i]--;
                        realcard[i]++;
                        cardNum++;
                        state = 0;
                        break;
                    }
                }
            }
        }
    }
    
    int nextRequireRank() {
        return Rank[(cnt + 1) % 13];
    }
    
    bool willChallenge(int player) {
        if(player == 1) {
            if(roundHolder == 4 && hand[player][nextRequireRank()]==0)
                return true;
            for(int i = 0; i < 13; i++) {
                if(hand[player][requireRank] + cardNum > 4)return true;
            }
            return false;
        }
        else if(player == 2) {
            if(roundHolder == 1 && hand[player][nextRequireRank()]==0)
                return true;
            return false;
        }
        else if(player == 3) {
            if(hand[player][requireRank] == 4)return true;
            return false;
        }
        else{
            if(check(roundHolder))return true;
            return false;
        }
    }
    
    bool challenge() {
        return !state;
    }
    
    int table[15];
    void takesBack(int player) {
        for(int i = 0; i < 13; i++) {
            hand[player][i] += table[i];
            table[i] = 0;
        }
    }
    
    void init() {
        memset(table,0,sizeof table);
        memset(hand,0,sizeof hand);
        memset(realcard,0,sizeof realcard);
    }
    
    int main() {
    //    IN_PC();
        char card[5];
        while(scanf("%s", card) != EOF) {
            init();
            hand[1][tran(card)]++;
            for(int i = 0; i < 12; i++) {
                scanf("%s", card);
                hand[1][tran(card)]++;
            }
            for(int i = 2; i <= 4; i++) {
                for(int j = 0; j < 13; j++) {
                    scanf("%s", card);
                    hand[i][tran(card)]++;
                }
            }
            cnt = 0;
            roundHolder = 1, requireRank = Rank[cnt % 13];
            int winner = 0;
            while(1) {
                putDown(roundHolder);
                for(int i = 0; i < 13; i++) {
                    table[i] += realcard[i];
                }
                for(int i = 1; i <= 3; i++) {
                    int challenger = (roundHolder % 4 + i-1)%4+1;
                    if(willChallenge(challenger)) {
                        if(challenge())
                            takesBack(roundHolder);
                        else
                            takesBack(challenger);
                    }
                }
                if(check(roundHolder)) {
                    winner = roundHolder;
                    break;
                }
                cnt++;
                requireRank = Rank[cnt % 13];
                roundHolder = roundHolder % 4 + 1;
            }
            for(int i = 1; i <= 4; i++) {
                if(winner==i){
                    printf("WINNER
    ");
                }
                else{
                    int flag = 0;
                    for(int j=0;j<13;j++){
                        for(int k=0;k<hand[i][Rank[j]];k++){
                            char ans[5];
                            NeTran(Rank[j],ans);
                            if(flag==0){
                                flag = 1;
                            }
                            else printf(" ");
                            printf("%s",ans);
                        }
                    }
                    puts("");
                }
            }
        }
        return 0;
    }
    

    D.80 Days

    CODE

    队友代码

    #include <stdio.h>
    #include <time.h>
    #include <algorithm>
    using namespace std;
    typedef long long ll;
    const int maxn = 2000005;
    
    ll val[maxn<<2];
    
    ll sum[maxn];
    
    void build(ll rt,ll l,ll r){
        if (l==r){
            val[rt] = sum[l];
        } else {
            ll mid = (l+r)/2;
            build(rt<<1,l,mid);
            build(rt<<1|1,mid+1,r);
            val[rt] = min(val[rt<<1],val[rt<<1|1]);
        }
    }
    
    ll query(ll rt,ll l,ll r,ll L,ll R){
        if (L<=l&&r<=R){
            return val[rt];
        } else {
            ll mid = (l+r)/2;
            ll ret = 1e18;
            if (L<=mid) ret = min(ret,query(rt<<1,l,mid,L,R));
            if (mid<R) ret =min(ret,query(rt<<1|1,mid+1,r,L,R));
            return  ret;
        }
    }
    int main() {
        ll t;
        scanf("%lld",&t);
        while (t--){
            ll n,c;
            scanf("%lld%lld",&n,&c);
            for (int i=1;i<=n;i++) {
                scanf("%lld",&sum[i]);
            }
            for (int i=1;i<=n;i++) {
                ll tmp;
                scanf("%lld",&tmp);
                sum[i]-=tmp;
                sum[n+i]=sum[i];
            }
            for (ll i=1;i<=2*n;i++){
                sum[i]=sum[i-1]+sum[i];
            }
            build(1,1,2*n);
            ll ans = -1;
            for (int i=1;i<=n;i++){
                if ( (sum[i]-sum[i-1]+c>=0)&&  query(1,1,2*n,i,n+i-1) + c >= sum[i-1] ){
                    ans = i;
                    break;
                }
            }
            printf("%lld
    ",ans);
        }
        return 0;
    }
    
  • 相关阅读:
    tile38 复制配置
    The Guardian’s Migration from MongoDB to PostgreSQL on Amazon RDS
    tile38 一款开源的geo 数据库
    sqler sql 转rest api 的docker 镜像构建(续)使用源码编译
    sqler sql 转rest api javascript 试用
    sqler sql 转rest api redis 接口使用
    sqler sql 转rest api 的docker image
    sqler sql 转rest api 的工具试用
    apache geode 试用
    benthos v1 的一些新功能
  • 原文地址:https://www.cnblogs.com/NeilThang/p/9691526.html
Copyright © 2011-2022 走看看