zoukankan      html  css  js  c++  java
  • 测试总结(没有rank1)

    一个初三蒟蒻不可能rank1.jpg

    T1:

    给出两个单词 (开始单词和结束单词) 以及一个词典。 找出从开始单词转换到结束单词,
    所需要的最短转换序列。转换的规则如下:
    1、每次只能改变一个字母
    2、转换过程中出现的单词(除开始单词和结束单词)必须存在于词典中
    例如:
    开始单词为:hit
    结束单词为:cog
    词典为:[hot,dot,dog,lot,log,mot]
    那么一种可能的最短变换是: hit -> hot -> dot -> dog -> cog,
    所以返回的结果是序列的长度 5;
    注意:
    1、如果不能找到这种变换,则输出 0;
    2、词典中所有单词长度一样;
    3、所有的单词都由小写字母构成;
    4、开始单词和结束单词可以不在词典中。

    每个词长度不大于5,词数不超过30

    看上去好难...要各种比较字符串,判断变化...

    然而这是一道搜索题(看数据范围)

    代码:

    #include<iostream>
    #include<cstdio>
    #include<algorithm>
    #include<cstring>
    #include<string>
    #include<stdio.h>
    using namespace std;
    char tar[6];       //目标字符串
    char sta[6];       //初始字符串
    char index[35][6]; //字典
    int l;             //字符串长度
    int minn=35;    //答案,最终要取最小,设一个怎么都算不到的极大值,
    int t=1;           //处理读入的指针(并不是*指针)
    bool used[35];    //查看在搜索时是否用过,毕竟一个词不能用两遍,也用不了两遍...
    inline void search(int step,char a[6]){    //用这两个变量step传递步数状态,a数组传递目前字符状态
        int sum=0;
        for(int i=0;i<l;i++)
            if(a[i]!=tar[i])
                sum++;         //比较a数组与tar是否只有一步之遥
        if(sum==1)
            minn=min(minn,step);
        for(int i=1;i<=t;i++){
            if(used[i])continue;
            sum=0;
            int p;    //保存与a不同的字符下标方便深搜回溯
            char c;  //保存原先的a的被替换字符以便回溯
            for(int j=0;j<l;j++){
                if(a[j]!=index[i][j])
                    sum++,p=j;
            }
            if(sum==1){
                c=a[p];
                a[p]=index[i][p];
                used[i]=1;
                search(step+1,a);
                a[p]=c;    //反悔操作
                used[i]=0;
            }
        }
    }
    int main(){
        //freopen("word.in","r",stdin);
        scanf("%s",sta);
        scanf("%s",tar);
        l=strlen(sta);
        while(scanf("%s",index[t])!=EOF)   //输入处理,之前对这种无限制输入很头疼
            t++;
        search(2,sta);
        if(minn!=35)
            printf("%d
    ",minn);
        else
            printf("0
    ");   //无解的特判
        return 0;
    }

    总而言之,一个1h10min的搜索题

    T2

    对于 n=4 时,对应的集合 s={4,3,2,1},他的非空子集有 15 个
    当 n=4 时,集合{4,3,2,1}的 15 个子集分别对应于 4 位二进制数:
    {1}:0001;{2}:0010;{1,2}:0011;{3}:0100,…,{1,2,3,4}:1111。
    把二进制数相对应的十进制数的 1,2,3,…,15 分别作为相应集合的编号。
    如子集{1,2,4}对应的二进制数是 1011,相应的十进制数是 11,所以子集{1,2,4}的编号
    为 11。
    任务:
    对于给定的 n 和 m,输出集合{1,2,…,n}的编号为 m 的子集。

    思路是状态压缩dp的核心

    本题的n没有任何用处,仅是对m的数位分析,

    主要算法思路就是把m的二进制展开,某一位为1则输出该数,为0则表示没有该数,不输出

    一道大水题

    代码:

    #include<iostream>
    #include<cstdio>
    using namespace std;
    int n,m;
    int main(){
        scanf("%d%d",&n,&m);
        n=1;
        while(m){
            if(m&1)printf("%d ",n);
            n++;
            m>>=1;
        }return 0;
    }

    快速幂处理方法不解释

    T3(毒瘤,不给大样例,没有小数据,1分都没骗到...):

    有 n 个城市,编号 1~n。其中 i 号城市的繁华度为 pi。省内有 m条可以双向同行的高速
    公路,编号 1~m。编号为 j 的高速公路连接编号为 aj 和 bj 两个城市,经过高速公路的费用
    是 wj。若从城市 x 出发到某城市 y,除了需要缴纳高速公路费用,还要缴纳“城市建设费”
    (为从 x 城市到 y 城市所经过的所有城市中繁华度的最大值,包括 x 和 y 在内)。
    现提出 q 个询问,每个询问给出一组 x 和 y,你需要回答从 x 出发到 y 城市,所需要的
    最低交通费(高速公路费+城市建设费)是多少。

    刚刚测试时代码蜜汁不见了先把代码粘上来

    #include<iostream>
    #include<cstdio>
    #include<algorithm>
    #include<cstring> 
    using namespace std;
    int dis[255][255];
    int pm[255][255];
    int p[255];
    int n,m,q;
    int main(){
        //freopen("road.in","r",stdin);
        //freopen("road.out","w",stdout);
        memset(dis,0x3f,sizeof dis);
        scanf("%d%d%d",&n,&m,&q);
        for(int i=1;i<=n;i++)
            scanf("%d",&p[i]);
        for(int i=1;i<=m;i++){
            int a,b,c;
            scanf("%d%d%d",&a,&b,&c);
            dis[a][b]=min(dis[a][b],c);
            dis[b][a]=min(dis[a][b],c);
            pm[a][b]=max(p[a],p[b]);
            pm[b][a]=max(p[a],p[b]);
        }
        for(int k=1;k<=n;k++){
            for(int i=1;i<=n;i++){
                for(int j=1;j<=n;j++){
                    if(dis[i][j]+pm[i][j]>dis[i][k]+dis[k][j]+max(pm[i][k],pm[k][j])){
                        dis[i][j]=dis[i][k]+dis[k][j];
                        pm[i][j]=max(pm[i][k],pm[k][j]);
                    }
                }
            }
        }
        while(q){
            q--;
            int x,y;
            scanf("%d%d",&x,&y);
            printf("%d
    ",dis[x][y]+pm[x][y]);
        }return 0;
    }

    这是10分代码...然而当时我并没有10分(当时没有判重边)

    标程:

    #include<iostream>
    #include<cstring>
    #include<cstdio>
    #include<queue>
    #include<algorithm>
    using namespace std;
    int n,m,q,p[300],aj,bj,wj,x,y,f[300][300],a[300][300],top,t[300];
    int cmp(int x,int y)
    {
        return p[x]<p[y];
    }
    int main()
    {
        freopen("road.in","r",stdin);
        freopen("road.out","w",stdout);
        memset(a,63,sizeof(a));
        top=0;
        scanf("%d%d%d",&n,&m,&q);
        for(int i=1;i<=n;i++)
            scanf("%d",&p[i]);
        for(int i=1;i<=m;i++)
        {
            scanf("%d%d%d",&aj,&bj,&wj);
            a[aj][bj]=min(a[aj][bj],wj);
            a[bj][aj]=min(a[bj][aj],wj);
        }
        for(int i=1;i<=n;i++)       //初始化
        {
            a[i][i]=0;
            t[i]=i;                 //t数组为城市编号,将其初始为城市编号
        }
        sort(t+1,t+1+n,cmp);        //按照城市繁华度排序对接下来的Floyd有正确性保证
        for(int i=1;i<=n;i++)
            for(int j=1;j<=n;j++)
                f[i][j]=a[i][j]+max(p[i],p[j]);   //初始化f数组(答案)
        for(int k=1;k<=n;k++)       //保证p[t[k]]递增的Floyd
            for(int i=1;i<=n;i++)
                for(int j=1;j<=n;j++)
                {
                    a[i][j]=min(a[i][j],a[i][t[k]]+a[t[k]][j]);   //对边的松弛
                    f[i][j]=min(f[i][j],a[i][j]+max(p[i],max(p[j],p[t[k]]))); //取最大的p为价值,对答案进行优化
                }
        for(int i=1;i<=q;i++)
        {
            scanf("%d%d",&x,&y);
            printf("%d
    ",f[x][y]);
        }
        fclose(stdin);
        fclose(stdout);
        return 0;
    }
    /*
    先理一下排序后k(t数组的角标),t与p的对应关系
    仔细思考,嗯,证毕
    排序后自然k为1-n递增序列,角标自然递增
    t是p对应城市编号,是某种意义上的“有序排列”,然而其值无序,用其值作对应角标的p数组有序递增
    p显然是城市繁华度,也是值无序,通过某种特定的访问是有序的,
    也就是以t[k]为角标的p是第k大的繁华度,t[k]为繁华度为第k大的城市编号
    (晕了)
    所以现在我们有两种访问p数组的途径,一是根据城市标号直接查询,如将f数组初始化时的操作
    二是按照大小顺序访问p,比如进行Floyd时的访问顺序
    排序后的目的呢?
    排序使p数组递增,使得Floyd时枚举到的p[t[k]]一定是1-k中最大的,以保证正确性
    原理是啥?
    排序
    通过排序来保证数据的有序出现,以免在优化过程中将路上的最大p值"优化"掉
    比如,我在枚举k点时已经将dis[a][b]优化,此时路中央有个p最大的城市mfb(无恶意)
    然而继续枚举,发现枚举到了同一条路上的gc(同上),发现p[gc]<p[mfb],于是按照公式取min,把mfb"优化"掉了
    那么就不再能保证正确性,
    总结下,使p有序能够保证全面地枚举以求正确结果
    */
  • 相关阅读:
    第一阶段冲刺总结
    读书笔记之梦断代码1
    第二次站立会议5
    第二次站立会议4
    第二次站立会议3
    第二次站立会议2
    Java学习
    项目冲刺第十天
    项目冲刺第九天
    项目冲刺第八天
  • 原文地址:https://www.cnblogs.com/648-233/p/11010681.html
Copyright © 2011-2022 走看看