zoukankan      html  css  js  c++  java
  • 2013金山西居挑战赛初赛1—转自blog.csdn.net/asdfgh0308/

    刚水了这场比赛:2013金山西山居创意游戏程序挑战赛——初赛(1)。
    简要题解如下:
    1001 魔法串:
    问第二个串能不能变成第一个串。
    显然的DP问题。dp[i][j]表示第二串前j个变成第一串前i个是否可行。
    转移就是
    if (dp[i][j-1]==1) dp[i][j]=1;
    if (dp[i-1][j-1]==1&&g[t[j]][s[i]]==1){dp[i][j]=1;}
    g[a][b]为1表示a字符能变成b字符。

    #include<iostream>
    #include<cstdio>
    #include<cstring>
    using namespace std;
    #define NN 1010
    
    int cas,tcas,i,g[300][300],j,l1,l2,dp[NN][NN],m;
    char s[NN],t[NN],sa[50],sb[50];
    
    int main(){
        scanf("%d",&tcas);
        for(cas=1;cas<=tcas;++cas){
            scanf("%s%s",s+1,t+1);
            s[0]=t[0]='*';
            scanf("%d",&m);
            memset(g,0,sizeof(g));
            for(i='a';i<='z';++i){g[i][i]=1;}
            for(i=1;i<=m;++i){
                scanf("%s%s",sa,sb);
                g[sa[0]][sb[0]]=1;
            }
    
    
            memset(dp,0,sizeof(dp));
            l1=strlen(s)-1;l2=strlen(t)-1;
            for(i=0;i<=l2;++i) dp[0][i]=1;
            for(i=1;i<=l1;++i){
                for(j=i;j<=l2;++j){
    
                    if (dp[i][j-1]==1){
                        dp[i][j]=1;
                    }
                    if (dp[i-1][j-1]==1&&g[t[j]][s[i]]==1){
                        dp[i][j]=1;
                    }
                }
            }
            printf("Case #%d: ",cas);
            printf("%s\n",dp[l1][l2]?"happy":"unhappy");
        }
        return 0;
    }
    View Code

    1002 比赛难度:
    人品不错,前几天刚在中南月赛中做了一个类似的题目:求第m小的三个素数相乘所得的数。(想想怎么做?)

    显然,m很小,很容易想到构造的方式。问题是怎么构造出比较小的可能的状态。
    用优先队列类似宽搜的方式,每次加入最有可能的几个状态。然后在队列中取最小的状态继续搜索。

    将题目按照难度排序。
    这题状态可以记录为两个值,a:当前所取的总难度和,b:最后取的一道题的题号。
    那么从这个状态拓展的下一个最有可能的状态就是
    1:去掉第b道题,取第b+1道题;
    2:取现在状态所取的所有题加上第b+1道题。

    这样搜索下去就能不重复不遗漏地取到所有的状态。而每次取出一个状态最多只会加入两个状态,这样时间空间都是0(M)。

    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #include<queue>
    #include<map>
    #include<algorithm>
    using namespace std;
    #define NN 20100
    
    struct node{
        int a,b;
        bool operator <(const node &y)const{
            if (a==y.a) return b>y.b;
            else return a>y.a;
        }
    }tn,un;
    
    priority_queue<node> q;
    int v[NN];
    
    int main(){
        int tcas,cas,n,m,i,a,b,tot,ans;
        scanf("%d",&tcas);
        for(cas=1;cas<=tcas;++cas){
            scanf("%d%d",&n,&m);
            for(i=1;i<=n;++i){
                scanf("%d",&v[i]);
            }
            sort(v+1,v+n+1);
            while(!q.empty()) q.pop();
            tn.a=v[1];tn.b=1;
            q.push(tn);
            tot=0;
            while(!q.empty()){
                un=q.top();q.pop();
                tot++;
                //printf("%d %d\n",un.a,un.b);
                if (tot>=m) {ans=un.a;break;}
                a=un.a;b=un.b;
                if (b<n){
                tn.a=a-v[b]+v[b+1];tn.b=b+1;
                q.push(tn);
                tn.a=a+v[b+1];tn.b=b+1;
                q.push(tn);
                }
    
            }
            printf("Case #%d: %d\n",cas,ans);
        }
        return 0;
    }
    View Code

    1003 CD操作:
    其实CD这个命令可以直接输入目标文件夹的绝对路径,这样一次就够了我会乱说?

    这题的cd只能返回上一层,而向下可以一次到达。
    显然的LCA问题,求出两个目录的最小公共祖先目录,一直向上找到这个目录为止,再一次(或是0次)走到目标目录即可。

    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #include<cmath>
    #include<map>
    using namespace std;
    #define NN 100005
    #define max(a,b) (a>b?a:b)
    #define min(a,b) (a<b?a:b)
    
    int mr[NN*2][18],first[NN],next[NN],w[NN],R[NN];
    int tote,totn;
    int i,deg[NN],a,b,cas,n,root,ans;
    
    map<string,int> mp;
    char ts1[50],ts2[50];
    string str1,str2;
    
    struct node{
           int o,dep;
    }aa[NN*2];
    
    void lcadfs(int now,int dep){
         aa[++totn].o=now;
         aa[totn].dep=dep;
         int e;
         for(e=first[now];e!=-1;e=next[e]){
            lcadfs(w[e],dep+1);
            aa[++totn].o=now;
            aa[totn].dep=dep;
         }
    }
    
    void rmqinit(){
         int m=-1,k=totn;
         while(k) {m++;k>>=1;}
         int i,j;
         for(i=1;i<=totn;i++) {mr[i][0]=i;}//mr记录最小值位置
         for(i=1;i<=m;i++){
             for(j=1;j<=totn;j++){
                 mr[j][i]=mr[j][i-1];
                 if (j+(1<<(i-1))<=totn) {
                       if (aa[mr[j][i]].dep>aa[mr[j+(1<<(i-1))][i-1]].dep){
                           mr[j][i]=mr[j+(1<<(i-1))][i-1];
                       }
                 }
             }
         }
    }
    
    int rmqmin(int l,int r){
        int m=-1,k=r+1-l;
        while(k) {k>>=1;m++;}
        if (aa[mr[l][m]].dep<aa[mr[r+1-(1<<m)][m]].dep){
            return mr[l][m];
        }
        else return mr[r+1-(1<<m)][m];
    }
    
    
    
    
    int main(){
        int m,tots;
        scanf("%d",&cas);
        while(cas--){
           mp.clear();
           scanf("%d%d",&n,&m);
           for(i=1;i<=n;i++){first[i]=-1;deg[i]=0;}
           tote=0;
           tots=0;
           for(i=1;i<=n-1;i++){
               scanf("%s%s",ts1,ts2);
               str1=ts1;str2=ts2;
               if (mp[str1]==0) mp[str1]=++tots;
               if (mp[str2]==0) mp[str2]=++tots;
               b=mp[str1];a=mp[str2];
               tote++;
               next[tote]=first[a];
               first[a]=tote;
               w[tote]=b;
               deg[b]++;
           }
           for(i=1;i<=n;i++)   if (deg[i]==0) {root=i;break;}
           totn=0;
           lcadfs(root,0);
           memset(R,0,sizeof(R));
    
           for(i=1;i<=totn;i++){
               if (!R[aa[i].o]) R[aa[i].o]=i;
           }
    
           rmqinit();
           int tmp;
           for(i=1;i<=m;++i){
                scanf("%s%s",ts1,ts2);
                str1=ts1;str2=ts2;
                a=mp[str1];b=mp[str2];
                if (R[a]>=R[b]) tmp=rmqmin(R[b],R[a]);
                else tmp=rmqmin(R[a],R[b]);
                ans=aa[R[a]].dep-aa[tmp].dep;
                if (aa[tmp].o!=b) ans+=1;
                printf("%d\n",ans);
            }
        }
        return 0;
    }
    View Code

     

  • 相关阅读:
    linux下解压命令详解
    SSL简介及工作原理
    在CentOS中安装gcc配置c语言开发环境(转)
    JTable表格(隐藏表头)(转)
    一个云平台开源项目Eucalyptus
    「CF645E」 Intellectual Inquiry
    「CERC2017」Donut Drone
    洛谷P3943 星空
    「CSPS 2019」格雷码
    洛谷P3941 入阵曲
  • 原文地址:https://www.cnblogs.com/luandizuiren/p/3084482.html
Copyright © 2011-2022 走看看