考试整理

今天又进行了一波校内胡测

来整理一波

T1 单词序列

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

我们毫不经意的就想到了队列的做法

将起点设置为开始的单词

终点设置为目标单词

然后进行一波操作

将每一个字母进行匹配

然后能改就改(不能改就在最后cout<<0)

类似于BFS

找到最短的距离

然后输出

#include<iostream>
#include<cstdio>
#include<cstring>
#include<cmath>
#include<iomanip>
#include<string>
#include<algorithm>
#include<cstdlib>
#include<queue>
using namespace std;
struct node
{
    string word;
    int ans;
}s[31];
string begin,end;
bool b[31],bj;
int length;
queue<int> q;
int sum;
int QwQ(string x,string y)
{
    int sum=0;
    for(int i=0;i<length;i++) 
    {
        if(x[i]!=y[i]) 
        {
            sum++;
        }
    }
    return sum;
}
int main()
{
    freopen("word.in","r",stdin);
    freopen("word.out","w",stdout);
    cin>>begin>>end;
    length=begin.size();
    char ch;
    s[1].word=begin;
    int i=2;
    while(cin>>s[i].word) 
    {
        i++;
    }
    s[i].word=end;
    q.push(1);
    while(!q.empty())
    {
        int num=q.front();
        q.pop(); 
        if(s[num].word==end) 
        {
            printf("%d",s[num].ans+1);
            bj=1;
            break;
        }
        for(int j=1;j<=i;j++)
        {
            if(QwQ(s[num].word,s[j].word)==1&&!b[j])
            {
                s[j].ans=s[num].ans+1;
                q.push(j);
                b[j]=1;
            }
        }
    }
    if(!bj) 
    {
        printf("0");
    }
    return 0;
}

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 的子集。
【输入格式】
n,m
【输出格式】
集合的第 m 个子集的元素, 元素从小到大输出, 中间一个空格隔开。
【样例输入】
4 11
【样例输出】
1 2 4
【数据范围及约定】
100%的数据: n<=20,m<=2^n-1

直接打暴力

#include<iostream>
#include<cstdio>
#include<cstring>
#include<cmath>
#include<iomanip>
#include<string>
#include<algorithm>
#include<cstdlib>
#include<queue>
using namespace std;
inline int read()
{
    int X=0,w=1; 
    char c=getchar();
    while(c<'0'||c>'9')
    { 
        if (c=='-')
        {
            w=-1; 
            c=getchar();
        } 
    }
    while(c>='0'&&c<='9')
    {
        X=(X<<3)+(X<<1)+c-'0';
        c=getchar();
    } 
    return X*w;
}
long long n,m;
long long s[1100000];
int main()
{
    freopen("subset.in","r",stdin);
    freopen("subset.out","w",stdout);
    n=read();
    m=read();
    for(int i=n-1;i>=0;i--)
    {
        if(m>=(1<<i))
        {
            s[i]=1;
            m=m-(1<<i);
        }
        if(m==0)
        {
            break;
        }
    }
    for(int i=0;i<n;i++)
    {
        if(s[i])
        {
            printf("%d ",i+1);
        }
    }
    return 0;
} 

T3 城市交通费

【问题描述】
n 个城市, 编号 1~n。 其中 i 号城市的繁华度为 pi。 省内有 m 条可以双向同行的高速
公路, 编号 1~m。 编号为 j 的高速公路连接编号为 aj bj 两个城市, 经过高速公路的费用
wj。 若从城市 x 出发到某城市 y, 除了需要缴纳高速公路费用, 还要缴纳“城市建设费”
(为从 x 城市到 y 城市所经过的所有城市中繁华度的最大值, 包括 x y 在内) 。
现提出 q 个询问, 每个询问给出一组 x y, 你需要回答从 x 出发到 y 城市, 所需要的
最低交通费(高速公路费+城市建设费) 是多少。
【输入】
第一行三个整数 n,m,q
第二行 n 个整数, 表示 p1~pn
接下来 m 行中, 每行 3 个正整数, 第 j 行包含 AjBjWj
随后 Q 行每组两个正整数 xy 表示一组询问。
【输出】
共 Q 行, 为对 Q 个问题的回答: x 城市到 y 城市的最小交通费用。
【样例输入】
5 7 2
2 5 3 3 4
1 2 3
1 3 2
2 5 3
5 3 1
5 4 1
2 4 3
3 4 4
1 4
2 3
【样例输出】
8 9
【数据范围及约定】
n250m20000Q10000Pi10000Wj2000, 保证任意两个城市可以互相到达。
【样例说明】
图中, 代表城市的格子中第一个数字是城市编号, 第二个红色数字是该城市的繁华度。
1) 从城市 1 到城市 4 的最小交通费用路线是: 1 3 5 4; 公路费是 2+1+1=4; 城市建设费是
max{2,3,4,3}=4; 总交通费用 4+4=8
2) 从城市 2 到城市 3 的最小交通费用路线是: 2 5 3; 公路费是 3+1=4; 城市建设费是
max{5,4,3}=5; 总交通费用 4+5=9

这个题的思路为Floyd

32行之所以排序是因为在下面的41行中要算出所经过所有点的繁华度的最大值(需要保证p【t【k】】是从第一个城市到第k个城市的最大繁华度,这样就只需要比较p【i】,p【j】和p【t【k】】就可以了)

至于40行到41行是如何实现的:

我们先假设a【i】【j】被更新,那么只有在原来未更新的f【i】【j】(=a【i】【j】+max(p【i】,p【j】))大于更新后的a【i】【j】+max(p【i】,max(p【j】,p【t【k】】))时答案f【i】【j】才会被更新

再假设a【i】【j】未被更新,那么不管p【t【k】】是大是小,答案f【i】【j】总不会受到影响

即只有a【i】【j】被更新时,才有可能更新答案

这就保证了答案的准确性

 1 #include<iostream>
 2 #include<cstring>
 3 #include<cstdio>
 4 #include<queue>
 5 #include<algorithm>
 6 using namespace std;
 7 int n,m,q,p[300],aj,bj,wj,x,y,f[300][300],a[300][300],top,t[300];
 8 int cmp(int x,int y)//对繁华度的排序操作
 9 {
10     return p[x]<p[y];
11 }
12 int main()
13 {
14     freopen("road.in","r",stdin);
15     freopen("road.out","w",stdout);
16     memset(a,0x3f,sizeof(a));
17     top=0;
18     scanf("%d%d%d",&n,&m,&q);
19     for(int i=1;i<=n;i++)
20         scanf("%d",&p[i]);
21     for(int i=1;i<=m;i++)
22     {
23         scanf("%d%d%d",&aj,&bj,&wj);
24         a[aj][bj]=min(a[aj][bj],wj);//两个城市之间会有不止一条公路
25         a[bj][aj]=min(a[bj][aj],wj);//两个城市之间会有不止一条公路 
26     }
27     for(int i=1;i<=n;i++)
28     {
29         a[i][i]=0;//初始化,自己到自己为0 
30         t[i]=i;//记录标号 
31     }
32     sort(t+1,t+1+n,cmp);//类似于结构体,对于t数组关于p(繁华度)进行排序 
33     for(int i=1;i<=n;i++)
34         for(int j=1;j<=n;j++)
35             f[i][j]=a[i][j]+max(p[i],p[j]);//算出两条直接连边公路的总价值 
36     for(int k=1;k<=n;k++)//Floyd的过程 (多源最短路) 
37         for(int i=1;i<=n;i++)
38             for(int j=1;j<=n;j++)
39             {
40                 a[i][j]=min(a[i][j],a[i][t[k]]+a[t[k]][j]);//先算公路的代价 
41                 f[i][j]=min(f[i][j],a[i][j]+max(p[i],max(p[j],p[t[k]])));//算出答案 
42             }
43     for(int i=1;i<=q;i++)
44     {
45         scanf("%d%d",&x,&y);
46         printf("%d
",f[x][y]);//输出 
47     }
48     return 0;
49 }
原文地址:https://www.cnblogs.com/gongcheng456/p/11009876.html