2014年acm-icpc牡丹江regional网络赛经历

    距离退役已经快一年了,以前和我的队友在赛场上飞扬跋扈的日子现在回忆起来还是很爽的。
    今天是实验室2014年regional牡丹江赛区网络赛的日子,作为一名老队员我觉得参加这场比赛是一场义务。其实在去年我觉得我是可以不去的,因为有FG在,网络赛出线肯定是没有问题的。但是今年还是有点担心,不过因为我也好久不练了,虽然自己的水平肯定在学弟之下,但是感觉还是得刷一下存在感。
    比赛刚开始看了最后一题J题。一开始感觉虽然数据比较小,但是还是可以用KMP优化,然后就自己写了一个KMP版额代码,结果WA了。下面是WA了的代码:
#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
using namespace std;
const int maxn = 1010;
char s[maxn];
int next[maxn] , len;

bool judge_ABABA(int nn) {
    int lena = 2 * nn - len;
    int lenb = nn - 2 * lena;
    if(lena <= 0 || lenb <= 0) return false;
    int p1 = lena , p2 = lena + lenb , p3 = nn , p4 = nn + lenb , p5 = len - 1;
    for(int i=0;i<lena;i++) if(s[i] != s[p2+i] || s[i] != s[p4+i]) return false;
    for(int i=0;i<lenb;i++) if(s[p1+i] != s[p3+i]) return false;
    return true;
}
bool judge_ABABCAB(int nn) { // the same as AABA , some change
    int lena = nn + 1;
    int lenb = len - 3 * lena;
    if(lena <= 0 || lenb <= 0) return false;
    int p1 = lena , p2 = 2 * lena , p3 = len - lena , p4 = len;
    for(int i=0;i<lena;i++) if(s[i] != s[p1+i] || s[i] != s[p3+i]) return false;
    if(lena == 2 && s[0] == s[1]) return false;
    if(lena != lenb) return true;
    for(int i=0;i<lena;i++) if(s[i] != s[p2+i]) return true;
    return false;
}
bool j_ABABA() {
    for(int nn = next[len-1] + 1;nn!=-1;nn=next[nn]) {
        if(judge_ABABA(nn)) return true;
    }
    return false;
}
bool j_ABABCAB() {
    for(int nn = next[len-1];nn!=-1;nn=next[nn]) {
        if(judge_ABABCAB(nn)) return true;
    }
    return false;
}
int main() {
    int T;
    scanf("%d" , &T);
    while(T--) {
        scanf("%s" , s);
        len = strlen(s);
        int j=0;
        for(int i=0;i<len;i++) {
            if(isalpha(s[i])) s[j++] = s[i];
        }
        len = j;
        s[len] = 0;
        //printf("%s\n" , s);
        next[0] = -1;
        j = -1;
        for(int i=1;i<len;i++) {
            while(j >= 0 && s[i] != s[j+1]) j = next[j];
            if(s[i] != s[j+1]) next[i] = j;
            else {
                j ++;
                next[i] = j;
            }
        }
        //for(int i=0;i<len;i++) printf("%d " , next[i]);
        bool ok = false;
        if(j_ABABA()) ok = true;
        else if(j_ABABCAB()) ok = true;
        if(ok) puts("Yes");
        else puts("No");
    }
    return 0;
}
    当然作为一名老队员我觉得暴力肯定能过,但是暴力又不是我的风格,所以我就QQ了ZY让他找一个小学弟帮忙暴力过一下。事实证明后来暴力过了。
    这个时候ZY说C题是图论,而我在图论方面比较擅长,所以我就看了。看懂题目后的初始的5分钟内我的思路从无向图双连通分量变化到了dfs加并查集,变化到了简单的dfs,记忆化搜索。然后就按照思路来,大致是
cnt[i]表示i能涉及到
ok[i]表示i当前能够访问
vis[i]表示i已经访问到,这是记忆化搜索所做的标记,上面两个都是标记。然后代码就很清晰了,但是交上去WA了,只能怪自己好久不练了。下面是错误的代码:
#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
using namespace std;
const int maxn = 101000 , maxm = 404000;
int n , m , K , L;
struct Edge {
    int v , next;
    Edge () {}
    Edge (int v,int next) : v(v) , next(next) {};
}edge[maxm];
int E , head[maxn];
void init() {
    E = 0; memset(head,-1,sizeof(int)*(n+1));
}
void addedge(int u,int v) {
    edge[E] = Edge(v,head[u]); head[u] = E++;
    edge[E] = Edge(u,head[v]); head[v] = E++;
}
int st , rt;
//queue<int> q;
bool ok[maxn]; // can be solved
bool vis[maxn];  // has been solved
bool con[maxn]; // if a edge for i to st
int od[maxn];
void dfs(int u) {
    con[u] = true;
    if(!ok[u] || vis[u]) return;
    vis[u] = true;
    for(int i=head[u];i!=-1;i=edge[i].next) {
        int v = edge[i].v;
        con[v] = true;
        if(!ok[v] || vis[v]) continue;
        dfs(v);
    }
    return;
}
bool check() {
    //puts("vis:");
    //for(int i=1;i<=n;i++) if(vis[i]) printf("1");
    //else printf("0");
    //puts("");
    //puts("ok:");
    //for(int i=1;i<=n;i++) if(ok[i]) printf("1");
    //else printf("0");
    //puts("");
    puts("con:");
    for(int i=1;i<=n;i++) if(con[i]) printf("1");
    else printf("0");
    puts("");
}
int main() {
    int T;
    scanf("%d" , &T);
    while(T--) {
        scanf("%d%d%d" , &n,&m,&K);
        init();
        for(int i=1;i<=n;i++) {
            vis[i] = false;
            ok[i] = true;
            con[i] = false;
        }
        for(int i=0;i<K;i++) {
            scanf("%d" , &od[i]);
            ok[od[i]] = false;
        }
        while(m--) {
            int u , v;
            scanf("%d%d" , &u,&v);
            addedge(u , v);
        }
        scanf("%d" , &L);
        for(int i=0;i<L;i++) {
            scanf("%d" , &od[i]);
        }
        if(L < K) {
            puts("No");
            continue;
        }
        st = od[0];
        con[st] = 1;
        bool Ok = true;
        //check();
        for(int i=0;i<L;i++) {
            int u = od[i];
            ok[u] = true;
            if(!con[u]) { Ok = false; break; }
            dfs(u);
            //check();
            //*2*if(!vis[u]) { Ok = false; break; }
        }
        if(Ok) puts("Yes");
        else puts("No");
    }
    return 0;
}
    不过ZY还是没有辜负我的期望,找出了我代码中的错误,得到了正确的代码。下面是ZY正确的代码:
#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
using namespace std;
const int maxn = 101000 , maxm = 404000;
int n , m , K , L, cnt;
struct Edge {
    int v , next;
    Edge () {}
    Edge (int v,int next) : v(v) , next(next) {};
}edge[maxm] ;
int E , head[maxn] , flag[maxn] ;
void init() {
    cnt = 0;
    memset(flag, 0, sizeof(flag));
    E = 0; memset(head,-1,sizeof(int)*(n+1));
}
void addedge(int u,int v) {
    edge[E]  = Edge(v,head[u] );
    head[u]  = E++;
    edge[E]  = Edge(u,head[v] );
    head[v]  = E++;
}

void ddfs(int x) {
    if (flag[x] )
        return;
    flag[x]  = 1;
    cnt ++;
    for(int i=head[x] ;i!=-1;i=edge[i] .next) {
        int v = edge[i] .v;
        ddfs(v);
    }
}

int st , rt;
//queue<int> q;
bool ok[maxn] ; // can be solved
bool vis[maxn] ;  // has been solved
bool con[maxn] ; // if a edge for i to st
int od[maxn] ;
void dfs(int u) {
    con[u]  = true;
    if(!ok[u]  || vis[u] )
        return;
    vis[u]  = true;
    for(int i=head[u] ;i!=-1;i=edge[i] .next) {
        int v = edge[i] .v;
        con[v]  = true;
        if(!ok[v]  || vis[v] )
            continue;
        dfs(v);
    }
    return;
}
int main() {
    int T;
    scanf("%d" , &T);
    while(T--) {
        scanf("%d%d%d" , &n,&m,&K);
        init();
        for(int i=1;i<=n;i++) {
            vis[i]  = false;
            ok[i]  = true;
            con[i]  = false;
        }
        for(int i=0;i < K;i++) {
            scanf("%d" , &od[i] );
            ok[od[i] ] = false;
        }
        while(m--) {
            int u , v;
            scanf("%d%d" , &u,&v);
            addedge(u , v);
        }
        scanf("%d" , &L);
        for(int i=0;i<L;i++) {
            scanf("%d" , &od[i] );
        }
        ddfs(1);
        if(K != L || cnt != n){
            puts("No");
            continue;
        }
        st = od[0];
        con[st]  = 1;
        bool Ok = true;
        for(int i=0;i<L;i++) {
            int u = od[i] ;
            ok[u]  = true;
            if(!con[u] ) {
                Ok = false;
                break;
            }
            dfs(u);
        }
        if(Ok)
            puts("Yes");
        else
            puts("No");
    }
    return 0;
} 
    然后我就想到毛爷爷的一句话:“世界是我们的,也是你们的,但是不管怎么样还是你们的”。ZY加油!
    然后我看剩下的过的最多的是H题,但是想得太复杂了,最后还是没有想通。下面是错误的代码:
#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
using namespace std;
#define ll long long
const int maxn = 1010;
int T;
char s[maxn] , t[maxn] , s1[maxn] , s2[maxn] , s3[maxn];
void debug(int len1 , int len2) {
    printf("len1 is %d\n" , len1);
    printf("len2 is %d\n" , len2);
}
int main() {
    scanf("%d" , &T);
    while(T--) {
        scanf("%s" , s);
        strcpy(t , s);
        int len = strlen(s);
        bool ok = false;
        if(len == 1) {
            printf("%c\n" , s[0]-1);
            continue;
        }
        else if(len == 2) {
            if(s[0] <= s[1]) { printf("%c%c\n" , s[0],s[0]); continue; }
            else if(s[0] > '1') { printf("%c%c\n" ,s[0]-1,s[0]-1); continue; }
            else { puts("9"); continue; }
        }
        for(int i=1;i<len-1;i++) if(s[i] != '0') ok = true;
        if(s[0] > '1' || s[len-1] > '1') ok = true;
        if(ok == false) {
            for(int i=1;i<len;i++) printf("9");
            puts("");
            continue;
        }
        int len1 = 0 , len2 = 0;
        s1[len1++] = s[0];
        s2[len2++] = s[0];
        for(int i=1;i<len;i++) {
            s1[len1++] = s[i];
            if(len1+len2>=len) break;
            if(s[i] != s[i-1]) s2[len2++] = s[i];
            if(len1+len2>=len) break;
        }
        s1[len1] = s2[len2] = 0;
        //strrev(s2);
        for(int i=0;i<len2;i++) s3[i] = s2[len2-1-i]; s3[len2] = 0;
        strcpy(s2 , s3);
        //printf("%s%s\n" , s1 , s2);
        strcat(s1 , s2);
        if(strcmp(t , s1) > 0) {
            puts(s1);
            continue;
        }
        for(int ii=len-1;ii>=0;ii--) {
            if(s1[ii] > '0') {
                s1[ii] -= 1;
                for(int jj=ii+1;jj<len;jj++) s1[jj] = '9';
                strcpy(s , s1);
                len1 = 0 , len2 = 0;
                s1[len1++] = s[0];
                s2[len2++] = s[0];
                for(int i=1;i<len;i++) {
                    s1[len1++] = s[i];
                    if(len1+len2>=len) break;
                    if(s[i] != s[i-1]) s2[len2++] = s[i];
                    if(len1+len2>=len) break;
                }
                s1[len1] = s2[len2] = 0;
                //strrev(s2);
                for(int i=0;i<len2;i++) s3[i] = s2[len2-1-i]; s3[len2] = 0;
                strcpy(s2 , s3);
                //printf("%s%s\n" , s1 , s2);
                strcat(s1 , s2);
                if(strcmp(t , s1) > 0) {
                    puts(s1);
                    break;
                }
            }
        }

        //debug(len1,len2);
    }
    return 0;
}



  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值