Gym 101196 (East Central North America Regional Contest 2016)

本文解析了四道编程挑战题,包括加密算法破解、最短路径计算、字符串压缩优化及汉诺塔问题的解决策略。通过代码示例详细阐述了解题思路。

PROBLEM C D E G ARE INCLUDED.

Problem C The Key to Cryptography

题意:

         给出一种加密方式:密文 = 原文 + key(若 源key 的长度小于原文,则用原文补齐)的偏移量。现给出密文求原文。

思路:

         先利用 源key 译出原文的前几位,利用译出的原文翻译后面的原文。注意 源key 的长度可能大于原文

代码:

#include <bits/stdc++.h>
using namespace std;

int main()
{
    string str1,str2;
    while(cin>>str1>>str2){
        string ans;
        int len1=str1.size(),len2=str2.size();
        int pos=-1;
        for(int i=0;i<len2&&pos<len1-1;i++)
            ans+=(str1[++pos]-str2[pos]+26)%26+'A';
        for(int i=0;pos<len1-1;i++)
            ans+=(str1[++pos]-ans[i]+26)%26+'A';
        cout<<ans<<endl;
    }
}

Problem D Lost in Translation

题意:

         给出一个图,从顶点开始(English),寻找 到每个点优先满足路径最短时的最小花费。

思路:

         所谓路径最短优先,其实就是 bfs 逐层搜索。若同层中有指向同一节点但花费不同的边,取最小即可。每搜完一层统计一遍 ans,给搜到的点打上 vis 标记即可。

代码:

(略丑)

#include <bits/stdc++.h>
using namespace std;
const int INF=0x3f3f3f3f;

map <string,int> has;
vector <int> mp[105];
int n,m;
int color[105];
bool vis[105];
int cost[105][105];
queue <int> que;
int ans[105],cut;
stack <int> here;
void ini(){
    has.clear();
    cut=0;
    has["English"]=0;
    for(int i=0;i<=101;i++){
        mp[i].clear();
        color[i]=INF;
        vis[i]=0;
        ans[i]=INF;
    }
}
int make_color(){
    int fans=0;
    que.push(0);
    int pos,len,now;
    color[0]=0;
    vis[0]=1;
    int floor=0;
    while(!que.empty()){
        pos=que.front();
        que.pop();
        if(color[pos]>floor){
            while(!here.empty()){
                now=here.top();
                here.pop();
                if(!vis[now]){
                    fans+=ans[now];
                    cut++;
                }
                vis[now]=1;
                //cout<<now<<": "<<fans<<endl;
            }
            floor++;
        }
        len=mp[pos].size();
        for(int i=0;i<len;i++){
            now=mp[pos][i];
            if(color[pos]<color[now]){
                color[now]=color[pos]+1;
                que.push(now);
                if(!vis[now]){
                    ans[now]=min(ans[now],cost[pos][now]);
                    here.push(now);
                }
            }
        }
    }
    return fans;
}

int main()
{
    int x;
    string str,str1,str2;
    int pos1,pos2;
    while(cin>>n>>m){
        ini();
        for(int i=1;i<=n;i++){
            cin>>str;
            has[str]=i;
        }
        for(int i=0;i<m;i++){
            cin>>str1>>str2>>x;
            pos1=has[str1];pos2=has[str2];
            mp[pos1].push_back(pos2);
            mp[pos2].push_back(pos1);
            cost[pos1][pos2]=x;
            cost[pos2][pos1]=x;
        }
        int ffans=make_color();
        if(cut==n)
            cout<<ffans<<endl;
        else
            cout<<"Impossible"<<endl;
    }
}

Problem E Red Rover

题意:

          给出一个串,现允许使用一个字符代替一部分串以减小串的长度。问可以实现的最小的串的长度是多少。

思路:

          其实就是找符合 子串重复次数*子串长度 最大的子串。由于数据量很小,直接暴力可过。在求重复次数时用KMP加速一下更快。

代码:

#include <iostream>
#include <map>
#include <cstring>
#include <set>
#include <cstdio>
#include <string>
using namespace std;

int get(string str1,string str2){
    int ans=0;
    int len=str2.size();
    int ll=str1.size();
    for(int i=0;i<len+1-ll;i++){
        if(str1==str2.substr(i,ll)){
            ans++;
            i+=ll-1;
        }
    }
    return ans;
}
int main()
{
    string str1,str2;
    int ans[105][105],tlen;
    while(cin>>str1){
        memset(ans,0,sizeof(ans));
        int len=str1.size();
        int fans=len,fansi,fansj;
        for(int i=1;i<=len;i++){
            for(int j=0;j<len+1-i;j++){
                str2=str1.substr(j,i);
                ans[i][j]=get(str2,str1);
                tlen=len-ans[i][j]*i+ans[i][j]+i;
                if(fans>tlen){
                    fans=tlen;
                    fansi=i;
                    fansj=j;
                }
            }
        }
        cout<<fans<<endl;
    }
    return 0;
}


Problem G That’s One Hanoi-ed Teacher

题意:

         如题图给出题目要求的汉诺塔运行方式(就是最优的移动方式)。给出三根柱子上的盘子数及盘子的序号。问当前状态是否合法,若合法输出最少剩余几步即可完成汉诺塔的运行。

思路:

         没什么好的思路,故先打表,打表程序如下:

#include <bits/stdc++.h>
using namespace std;
int pos[150];
int n;
int len[4];
queue <int> que[150];
int move(int x,char a,char b)
{
    //printf("number..%d..form..%c..to..%c\n",x,a,b);
    pos[x]=b-'A'+1;
    for(int i=1;i<=n;i++)
        que[i].push(pos[i]);
}

int mission(int x,char a,char b,char c)
{
    if(x==1)
    move(1,a,c);
    else
    {
        mission(x-1,a,c,b);//将x-1从a借c移到b。
        move(x,a,c);
        mission(x-1,b,a,c);//将x-1从b借a移到c。
    }
    return 0;
}
int main()
{
    while(cin>>n){
        for(int i=1;i<=n;i++){
            pos[i]=1;
            que[i].push(1);
        }
        mission(n,'A','B','C');
        for(int i=1;i<=n;i++){
            cout<<i<<":";
            while(!que[i].empty()){
                cout<<' '<<que[i].front();
                que[i].pop();
            }
            cout<<endl;
        }
    }
    return 0;
}
打表结果:

可以发现规律,
首先对于最大的盘子 MAX,其前一半为 1 后一半为 3
     若第 N 个盘子的位置 和 N 的前半区间相同,那么取前一半区间向下寻找
         且在 N 前一半区间内,第 N - 1 个盘子的前一半和 N 前一半区间相同。
         对于第 N - 1 个盘子的后一半,当 N - 1 和 MAX 的奇偶性相同时按照 “321” 序排列,不同时按照“123”序。
             即:
             当 MAX 为奇数时,若 N - 1 为偶数则前后一半按照 “123” 的顺序排列
           (即若第 N - 1 个盘子的前一半为 1 ,那么后一半为 2。前一半是 3 ,那么后一半为 1)
                                              若 N - 1 为奇数则前后一半按照 “321” 的顺序排列
           (即若第 N - 1 个盘子的前一半为 1 ,那么后一半为 3。前一半是 3 ,那么后一半为 2)
             当 MAX 为偶数时,若 N - 1 为偶数则前后一半按照 “321” 的顺序排列
                                              若 N - 1 为奇数则前后一半按照 “123” 的顺序排列                                                     
     同理:
     若第 N 个盘子的位置 和 N 的后半区间相同,那么取后一半区间向下寻找
         且在 N 后一半区间内,第 N - 1 个盘子的后一半和 N 后一半区间相同。
         对于第 N - 1 个盘子的前一半,当 N - 1 和 MAX 的奇偶性相同时按照 “321” 序排列,不同时按照“123”序。
             即:
             当 MAX 为奇数时,若 N - 1 为偶数则前后一半按照 “123” 的顺序排列
           (即若第 N - 1 个盘子的后一半为 1 ,那么前一半为 3。后一半是 3 ,那么后一半为 2)
                                              若 N - 1 为奇数则前后一半按照 “321” 的顺序排列
           (即若第 N - 1 个盘子的后一半为 1 ,那么前一半为 2。后一半是 3 ,那么前一半为 1)
             当 MAX 为偶数时,若 N - 1 为偶数则前后一半按照 “321” 的顺序排列
                                              若 N - 1 为奇数则前后一半按照 “123” 的顺序排列



根据以上规律:我们可以预测下一个盘子可能的位置,逐层缩小解的范围,到最后一层得到答案。

代码:

#include <bits/stdc++.h>
using namespace std;
long long pos[60],n,x,two[60],ans,num,low,high,fans,tot;
bool lr;
int main()
{
    x=1;
    for(int i=0;i<=50;i++){
        two[i]=x;
        x*=2;
    }
    //...............以上先打好表求2的幂
    while(cin>>n){
        num=0;
        bool flag=1;
        lr=0;
        fans=0;
        for(int i=1;i<=3;i++){
            if(i!=1) cin>>n;
            num+=n;
            for(int j=1;j<=n;j++){
                cin>>x;
                pos[x]=i;
            }
        }
        tot=num;
        //............以上记录盘子的位置
        low=1;high=3;
        while(num&&flag){
            if(pos[num]==low){
                lr=0;
            }else if(pos[num]==high){
                lr=1;
            }else{
                flag=0;
            }
            //..................以上判断是在前一半还是在后一半,若都不在说明盘面是非法的
            if((tot%2==1&&num%2==0)||(tot%2==0&&num%2==1)){
                if(lr==0){
                    low=low;
                    if(low==1) high=3;
                    else high=low-1;
                }else{
                    high=high;
                    if(high==3) low=1;
                    else low=high+1;
                    fans+=two[num-1];
                }
            }else{
                if(lr==0){
                    low=low;
                    if(low==3) high=1;
                    else high=low+1;
                }else{
                    high=high;
                    if(high==1) low=3;
                    else low=high-1;
                    fans+=two[num-1];
                }
            }
            //...................以上是确定第 N - 1 个盘的前一半和后一半是哪两个柱子。
            //同时统计答案位置
            num--;
        }
        if(flag==0) cout<<"No"<<endl;
        else cout<<two[tot]-fans-1<<endl;//注意是问还剩多少步汉诺塔才能运行完毕。
    }
}





内容概要:本文详细介绍了MySQL中InnoDB存储引擎的逻辑存储结构及其表分区技术。InnoDB的逻辑存储单元由高到低依次为表空间、段、区、页和行,其中表空间包括系统表空间、独立表空间、通用表空间、Undo表空间和临时表空间,每种表空间具有不同的用途和管理方式。文章进一步讲解了表分区的概念与类型,包括RANGE、LIST、HASH、KEY以及多字段COLUMNS分区,阐述了分区的优势如提升查询性能、便于数据维护、支持跨物理设备存储等,并列举了实际SQL操作示例,帮助理解分区表的创建、修改、删除及重组等操作。同时指出了分区的限制条件,如最大分区数量、主键约束要求等。; 适合人群:具备一定MySQL数据库基础,从事数据库开发、运维或架构设计的技术人员,尤其是工作中涉及大数据量表管理与性能优化的1-3年经验研发人员。; 使用场景及目标:①深入理解InnoDB存储机制,优化数据库物理结构设计;②掌握表分区技术,应用于海量数据存储与高效查询场景,如日志系统、订单系统的时间分区设计;③通过分区实现数据归档、快速删除历史数据、提升查询性能等运维目标; 阅读建议:学习时应结合MySQL实际环境动手实践文中提供的SQL命令,重点关注表空间管理和分区策略的选择,理解其对性能和维护的影响,并注意分区使用中的限制条件以避免设计失误。
【采用BPSK或GMSK的Turbo码】MSK、GMSK调制二比特差分解调、turbo+BPSK、turbo+GMSK研究(Matlab代码实现)【采用BPSK或GMSK的Turbo码】MSK、GMS内容概要:本文主要介绍了采用BPSK或GMSK调制方式的Turbo码相关技术研究,重点涵盖GMSK调制下的二比特差分解调方法、Turbo码与BPSK/GMSK调制相结合的系统性能分析,并提供了完整的Matlab代码实现方案。研究内容包括调制解调原理、编码结构设计、误码率仿真及系统优化等关键环节,旨在通过仿真手段验证所提出方案的有效性和可靠性,帮助研究人员深入理解现代数字通信系统中的关键技术和其实现方法。; 适合人群:具备一定通信原理和Matlab编程基础,从事无线通信、信号处理、编码理论等相关领域的研究生、科研人员及工程技术人员。; 使用场景及目标:①掌握GMSK调制与Turbo码结合的系统设计与仿真方法;②学习二比特差分解调算法在实际通信系统中的应用;③通过Matlab代码实现提升对数字调制解调和信道编码技术的理解与实践能力;④为相关课题研究、毕业设计或工程项目提供参考和技术支持。; 阅读建议:建议读者结合文中提供的Matlab代码逐模块运行与调试,对照通信系统基本原理深入理解各环节功能,重点关注调制解调过程与Turbo译码的协同工作机制,并尝试修改参数以观察系统性能变化,从而达到理论与实践相结合的学习效果。
源码下载地址: https://pan.quark.cn/s/7958f591353c 在Java应用程序的开发过程中,尤其是针对SpringBoot项目的构建,IntelliJ IDEA(简称IDEA)被广泛地采纳为一个极为流行的集成开发平台。本文将系统性地阐述如何在IDEA环境中部署并执行一个SpringBoot项目,涵盖了必要的环境搭建、Maven的配置、JDK环境的设定以及数据库的设置等关键环节。在进行后续操作前,请确认已经安装了以下基础组件: 1. IDEA:作为一个专门用于Java应用程序开发的集成开发环境,它提供了丰富的功能选项和强大的代码辅助能力。 2. JDK1.8:由于SpringBoot项目通常基于Java 8版本或更新版本进行开发,因此需要在计算机系统中安装对应的JDK版本。 3. MySQL8.0:如果项目需求中涉及到MySQL数据库的使用,请确保该数据库已经安装并处于运行状态。 4. Maven:作为项目的构建工具,它负责管理和构建SpringBoot项目。 **步骤一:Maven的配置** 1. **未配置Maven的情况**:当系统内部没有预先配置Maven时,IDEA将采用其内置的Maven版本来进行构建工作。用户可以直接利用IDEA自带的默认配置。 2. **已配置Maven的情况**:对于拥有个人Maven配置的用户,需要在IDEA中进行相应的设置。通过访问`File` > `Settings` > `Build, Execution, Deployment` > `Build Tools` > `Maven`菜单路径,用户可以在`Maven home directory`字段中指定本地Maven安装的路径。此外,还需确保`...
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值