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有序能够保证全面地枚举以求正确结果
    */
  • 相关阅读:
    java+opencv实现图像灰度化
    java实现高斯平滑
    hdu 3415 单调队列
    POJ 3368 Frequent values 线段树区间合并
    UVA 11795 Mega Man's Mission 状态DP
    UVA 11552 Fewest Flops DP
    UVA 10534 Wavio Sequence DP LIS
    UVA 1424 uvalive 4256 Salesmen 简单DP
    UVA 1099 uvalive 4794 Sharing Chocolate 状态DP
    UVA 1169uvalive 3983 Robotruck 单调队列优化DP
  • 原文地址:https://www.cnblogs.com/648-233/p/11010681.html
Copyright © 2011-2022 走看看