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;
    }
    
  • 相关阅读:
    MySQL 中无法 insert 文件路径 中的 backward slash的解决方法
    生成颜色代码的 Java程序
    公积金贷款不受影响 组合贷款有特殊
    ADOMD.NET Client Object架构
    心情•笔记20061231
    微软所谓的"无人工介入的自动的机器翻译系统"
    游戏中的微软
    商业智能的个人理解
    无日
    从电影死亡笔记看商业智能在治安领域的应用
  • 原文地址:https://www.cnblogs.com/NeilThang/p/9691526.html
Copyright © 2011-2022 走看看