蓝桥杯2019年A组国赛

A.三升序列

题目大意:

本题为填空题,只需要算出结果后,在代码中使用输出语句将所填结果输出即可。

对于一个字母矩阵,我们称矩阵中的一个三升序列是指在矩阵中找到三个字母,它们在同一行,同一列,或者在同一 45 度的斜线上,这三个字母从左向右看、或者从上向下看是递增的。

例如,如下矩阵中

YQPD
BKEZ
AFYV

有 BKZ*、BEZAFYAFVAKP、*DEF 等 6 个三升序列。注意当三个字母是从左下到右上排列时,从左向右看和从上向下看是不同的顺序。

对于下面的 30 行 50 列的矩阵,请问总共有多少个三升序列?

VLPWJVVNNZSWFGHSFRBCOIJTPYNEURPIGKQGPSXUGNELGRVZAG
SDLLOVGRTWEYZKKXNKIRWGZWXWRHKXFASATDWZAPZRNHTNNGQF
ZGUGXVQDQAEAHOQEADMWWXFBXECKAVIGPTKTTQFWSWPKRPSMGA
BDGMGYHAOPPRRHKYZCMFZEDELCALTBSWNTAODXYVHQNDASUFRL
YVYWQZUTEPFSFXLTZBMBQETXGXFUEBHGMJKBPNIHMYOELYZIKH
ZYZHSLTCGNANNXTUJGBYKUOJMGOGRDPKEUGVHNZJZHDUNRERBU
XFPTZKTPVQPJEMBHNTUBSMIYEGXNWQSBZMHMDRZZMJPZQTCWLR
ZNXOKBITTPSHEXWHZXFLWEMPZTBVNKNYSHCIQRIKQHFRAYWOPG
MHJKFYYBQSDPOVJICWWGGCOZSBGLSOXOFDAADZYEOBKDDTMQPA
VIDPIGELBYMEVQLASLQRUKMXSEWGHRSFVXOMHSJWWXHIBCGVIF
GWRFRFLHAMYWYZOIQODBIHHRIIMWJWJGYPFAHZZWJKRGOISUJC
EKQKKPNEYCBWOQHTYFHHQZRLFNDOVXTWASSQWXKBIVTKTUIASK
PEKNJFIVBKOZUEPPHIWLUBFUDWPIDRJKAZVJKPBRHCRMGNMFWW
CGZAXHXPDELTACGUWBXWNNZNDQYYCIQRJCULIEBQBLLMJEUSZP
RWHHQMBIJWTQPUFNAESPZHAQARNIDUCRYQAZMNVRVZUJOZUDGS
PFGAYBDEECHUXFUZIKAXYDFWJNSAOPJYWUIEJSCORRBVQHCHMR
JNVIPVEMQSHCCAXMWEFSYIGFPIXNIDXOTXTNBCHSHUZGKXFECL
YZBAIIOTWLREPZISBGJLQDALKZUKEQMKLDIPXJEPENEIPWFDLP
HBQKWJFLSEXVILKYPNSWUZLDCRTAYUUPEITQJEITZRQMMAQNLN
DQDJGOWMBFKAIGWEAJOISPFPLULIWVVALLIIHBGEZLGRHRCKGF
LXYPCVPNUKSWCCGXEYTEBAWRLWDWNHHNNNWQNIIBUCGUJYMRYW
CZDKISKUSBPFHVGSAVJBDMNPSDKFRXVVPLVAQUGVUJEXSZFGFQ
IYIJGISUANRAXTGQLAVFMQTICKQAHLEBGHAVOVVPEXIMLFWIYI
ZIIFSOPCMAWCBPKWZBUQPQLGSNIBFADUUJJHPAIUVVNWNWKDZB
HGTEEIISFGIUEUOWXVTPJDVACYQYFQUCXOXOSSMXLZDQESHXKP
FEBZHJAGIFGXSMRDKGONGELOALLSYDVILRWAPXXBPOOSWZNEAS
VJGMAOFLGYIFLJTEKDNIWHJAABCASFMAKIENSYIZZSLRSUIPCJ
BMQGMPDRCPGWKTPLOTAINXZAAJWCPUJHPOUYWNWHZAKCDMZDSR
RRARTVHZYYCEDXJQNQAINQVDJCZCZLCQWQQIKUYMYMOVMNCBVY
ABTCRRUXVGYLZILFLOFYVWFFBZNFWDZOADRDCLIRFKBFBHMAXX
题解:

使用dfs暴力找即可,用dir数组标识5个方向:左到右,上到下,左下到右上,左上到右下,右上到左下(右下到左上是不符合要求的)

Code:
#include <bits/stdcpp.h>
using namespace std;
#define ioss ios::sync_with_stdio(false);cin.tie(NULL);cout.tie(NULL);
char a[35][55];
int dir[5][2]={0,1,1,0,1,1,-1,1,1,-1};
int ans;
bool in(int x,int y){
    return x>=1&&x<=30&&y>=1&&y<=50;
}
void solve(int x,int y){
    for(int i=0;i<5;++i){
        int tx=x,ty=y;
        while(in(tx,ty)){
            tx+=dir[i][0];
            ty+=dir[i][1];
            if(a[tx][ty]<=a[x][y])continue;
            int ttx=tx,tty=ty;
            while(in(ttx,tty)){
                ttx+=dir[i][0];
                tty+=dir[i][1];
                if(a[ttx][tty]<=a[tx][ty])continue;
                ans++;
            }
        }
    }
}
int main(){
    char c;
    for(int i=1;i<=30;++i){
        for(int j=1;j<=50;++j){
            a[i][j]=getchar();
        }
        c=getchar();
    }
    for(int i=1;i<=30;++i){
        for(int j=1;j<=50;++j){
            solve(i,j);
        }
    }
    cout<<ans; //156159
    return 0;
}

B.最优旅行

题目大意:

本题为填空题,只需要算出结果后,在代码中使用输出语句将所填结果输出即可。

中国的高铁四通八达,乘坐方便,小明经常乘坐高铁在城市间旅游。

现在,小明又有了一个长假,他打算继续乘坐高铁旅游。这次,他打算到下面的城市旅游。

上海、广州、长沙、西安、杭州、济南、成都、南京、昆明、郑州、天津、太原、武汉、重庆、南昌、长春、沈阳、贵阳、福州。

小明打算从北京出发,游览以上每个城市正好一次,最终回到北京。在每个城市(除北京外),小明都至少停留 24 小时。而当小明决定从一个城市去往另一个城市时,他只会选择有直接高铁连接的城市,不会在中途换乘转车。

下面是小明可以选择的车次,小明不会选择其他车次。

车次  出发站 到达站 出发时间 到达时间
G169   北京   上海   16:40   22:35
G21    北京   上海   19:08   23:40
G18    上海   北京   17:55   22:36
G68    广州   北京   11:13   21:10
G67    北京   广州   12:13   22:19
G1305  上海   广州   15:25   23:38
G86    广州   上海   08:00   14:50
G6122  广州   长沙   21:00   23:36
G6117  长沙   广州   17:55   20:39
G502   长沙   北京   07:36   14:24
G503   北京   长沙   14:41   21:14
G1359  上海   长沙   15:37   20:59
G1348  长沙   上海   09:00   13:41
G362   西安   上海   08:49   14:45
G1936  上海   西安   16:12   22:54
G87    北京   西安   14:00   18:20
G88    西安   北京   13:30   17:55
G98    西安   广州   09:57   17:39
G836   广州   西安   11:24   20:09
G1404  广州   杭州   15:56   23:25
G20    杭州   北京   07:48   12:20
G39    北京   杭州   19:04   23:22
G7355  上海   杭州   21:30   22:28
G7558  杭州   上海   07:06   08:12
G300   济南   上海   06:50   11:40
G333   北京   济南   19:55   21:55
G336   济南   北京   07:45   09:33
G2056  广州   济南   08:05   18:34
G2058  济南   广州   10:14   20:49
G350   成都   北京   07:00   14:46
G89    北京   成都   06:53   14:38
G1888  成都   南京   11:28   22:00
G7180  上海   南京   10:05   11:29
G7003  南京   上海   08:00   09:39
G7613  南京   杭州   16:19   17:40
G7604  杭州   南京   12:09   13:30
G1540  昆明   南京   10:20   21:14
G1539  南京   昆明   09:05   19:40
G2883  成都   昆明   08:51   14:29
G2884  昆明   成都   12:16   17:57
G1538  昆明   郑州   08:46   18:48
G1537  郑州   昆明   10:38   20:49
G2001  郑州   西安   07:52   10:24
G2002  西安   郑州   08:10   10:29
G2231  西安   重庆   17:06   22:56
G2232  重庆   西安   07:05   12:37
G8594  重庆   成都   06:50   08:07
G8599  成都   重庆   22:12   23:29
G1709  天津   重庆   08:05   19:39
G1710  重庆   天津   10:49   22:45
G8901  北京   天津   22:10   22:45
G8928  天津   北京   19:08   19:46
G2609  天津   太原   10:40   14:15
G2610  太原   天津   14:43   18:12
G1954  太原   上海   12:26   21:17
G1952  上海   太原   08:10   17:28
G686   郑州   太原   13:17   17:16
G688   太原   郑州   17:38   21:38
G1864  太原   杭州   12:50   21:10
G1862  杭州   太原   07:14   15:50
G91    北京   太原   08:40   11:07
G92    太原   北京   08:33   11:00
G694   太原   武汉   16:37   22:29
G692   武汉   太原   09:48   16:00
G1722  武汉   上海   08:00   11:53
G1720  上海   武汉   13:51   17:50
G858   西安   武汉   15:18   19:48
G856   武汉   西安   09:17   14:27
G365   天津   武汉   14:56   20:41
G366   武汉   天津   14:30   20:32
G294   长沙   天津   08:47   16:56
G292   天津   长沙   10:58   18:50
G696   长沙   太原   09:23   17:55
G698   太原   长沙   10:46   18:18
G1391  杭州   昆明   11:43   22:53
G1392  昆明   杭州   09:06   20:18
G1514  昆明   南昌   16:00   22:54
G1511  南昌   昆明   08:25   15:38
G1462  南昌   杭州   12:24   15:28
G1451  杭州   南昌   12:30   15:26
G1244  济南   长春   07:42   15:07
G1242  长春   济南   15:33   22:35
G8033  沈阳   长春   06:42   08:40
G1290  长沙   长春   07:21   21:09
G1292  长春   长沙   08:47   22:08
G400   长春   北京   08:32   14:48
G399   北京   长春   15:20   21:45
G1886  南京   成都   08:07   17:54
G579   南京   长沙   09:27   14:10
G580   长沙   南京   15:53   20:40
G1484  贵阳   南京   07:58   18:02
G2335  南京   贵阳   12:07   21:58
G2105  长沙   贵阳   13:17   16:55
G2116  贵阳   长沙   08:11   11:26
G2201  郑州   成都   07:10   13:19
G2212  成都   郑州   16:57   23:04
G1814  上海   郑州   14:15   18:12
G370   郑州   上海   07:33   12:02
G1274  武汉   沈阳   07:23   19:03
G1272  沈阳   武汉   07:32   19:20
G2869  重庆   昆明   07:43   11:55
G2870  昆明   重庆   14:52   19:09
G1335  重庆   上海   08:48   20:56
G1333  上海   重庆   11:39   23:29
G1759  南昌   重庆   07:08   14:45
G1761  重庆   南昌   15:12   22:23
G1493  南京   南昌   13:00   17:21
G1496  南昌   南京   09:04   13:25
G5314  南昌   福州   08:13   11:09
G5312  福州   南昌   18:30   21:25
G1256  长春   上海   11:53   22:54
G1258  上海   长春   09:08   20:05
G1284  沈阳   成都   07:02   21:47
G1282  成都   沈阳   09:06   23:13
G217   北京   沈阳   13:30   17:15
G218   沈阳   北京   08:11   11:58
G2604  沈阳   太原   15:34   23:00
G2602  太原   沈阳   07:44   15:14
G8664  贵阳   成都   19:15   22:35
G8691  成都   贵阳   11:11   14:31
G2958  贵阳   广州   14:03   20:26
G2960  广州   贵阳   07:27   13:43
G1521  武汉   贵阳   08:01   13:25
G1524  贵阳   武汉   14:23   19:33
G1609  福州   广州   08:16   14:15
G1607  广州   福州   14:55   21:05
G1696  昆明   福州   11:11   22:02
G1698  福州   昆明   08:41   19:28
G1636  福州   上海   12:26   16:55
G1631  上海   福州   07:54   12:15
G1642  福州   杭州   14:45   18:32
G1641  杭州   福州   18:55   22:38

小明出发的时间是第 1 天的中午 12:00。请问,小明游览完以上城市正好一次,最终回到北京,最快需要多少分钟(请注意单位为分钟,请注意除北京外的城市需要至少停留 24 小时,即最少停留 1440 分钟)。

题解:

一共20个城市,使用二进制压缩标识状态,不过还需要加一维现在在哪个城市

dfs搜索+记忆化剪枝

注意:

  1. 每个城市都只去过一次,最后需要回到北京
  2. 回到北京后是不需要加24小时的,要记得减掉多加的24小时
Code:
#include <bits/stdcpp.h>
using namespace std;
#define ioss ios::sync_with_stdio(false);cin.tie(NULL);cout.tie(NULL);
#define novis(v,sta) !((sta>>(v-1))&1)
struct edge{
    int v,next,a,b;
}e[200];
int aim,head[25];
void add(int u,int v,int a,int b){
    e[++aim].next=head[u];
    head[u]=aim;
    e[aim].v=v;
    e[aim].a=a;
    e[aim].b=b;
}
int f[(1<<20)+10][21];
int ans=0x3f3f3f3f;
void dfs(int u,int sta,int now,int t){
    if(u==1&&sta!=0&&sta!=(1<<20)-1)return;
    if(t>=f[sta][u])return;
    if(t>=ans)return;
    f[sta][u]=t;
    if(sta==(1<<20)-1){
        ans=t;
        return;
    }
    for(int i=head[u];i;i=e[i].next){
        int v=e[i].v,a=e[i].a,b=e[i].b;
        if(novis(v,sta)){ //没访问过
            if(a>now){
                if(b>a){
                    dfs(v,sta|(1<<(v-1)),b,t+b+24*60-now);
                }else{
                    dfs(v,sta|(1<<(v-1)),b,t+b+2*24*60-now);
                }
            }else{
                if(b>a){
                    dfs(v,sta|(1<<(v-1)),b,t+b+2*24*60-now);
                }else{
                    dfs(v,sta|(1<<(v-1)),b,t+b+3*24*60-now);
                }
            }
        }
    }
}
int main(){
    int n=20,m=132;
    int u,v,a1,a2,b1,b2;
    for(int i=1;i<=132;++i){
        scanf("%d   %d   %d:%d   %d:%d",&u,&v,&a1,&a2,&b1,&b2);
        add(u,v,a1*60+a2,b1*60+b2);
    }
    memset(f,0x3f,sizeof f);
    dfs(1,0,12*60,0);
    cout<<ans-24*60;  //41613
    return 0;
}

C.骰子制造

题目大意:

这个题,题意很不清晰,网上也搜不到相应的题解,就不做了

D.序列求和

题目大意:

本题为填空题,只需要算出结果后,在代码中使用输出语句将所填结果输出即可。

image-20230604161956874

题解:

直接暴力做不出来,(别问我为啥知道)

在草稿纸上列出前几项后发现规律:将一个数质因数分解,每个质因数对应的(指数+1)乘起来就是这个数的因数个数。

大概能感觉到 2,3,5,7 就已经可以构造出大部分的Si了,所以直接四层循环,枚举每个质数的指数,去更新Si的最小值即可。

每层大概枚举到100,以前一直以为1s只能跑1千万次(1e7)的计算量,但实际上如果常数小的话,1个亿(1e8)的运算量也是能很快跑完的。

以下为当时 O(1e8) 的用时:

image-20230604162550329
Code:
#include<bits/stdcpp.h>
using namespace std;
typedef unsigned long long ll;
ll qpow(ll a,ll b){
    ll ans=1;
    while(b){
        if(b&1)ans*=a;
        a*=a;
        b>>=1;
    }
    return ans;
}
ll ans;
ll res[61];
int l=100;
int main(){
    for(int a1=0;a1<=l;a1++){
        for(int a2=0;a2<=a1;a2++){
            for(int a3=0;a3<=a2;a3++){
                for(int a4=0;a4<=a3;a4++){ //后面的指数没必要比前面的大
                    int t=(a1+1)*(a2+1)*(a3+1)*(a4+1);
                    if(t<=60){
                        ll tmp=(ll)(qpow(2,a1)*qpow(3,a2)*qpow(5,a3)*qpow(7,a4));
                        if(tmp<res[t]||res[t]==0){
                            res[t]=tmp;
                        }
                    }
                }
            }
        }
    }
    for(int i=1;i<=60;i++) ans+=res[i];
    cout<<ans; //292809912969717649
}

E.无方集合

题目大意:

本题为填空题,只需要算出结果后,在代码中使用输出语句将所填结果输出即可。

小明不是很喜欢完全平方数,他甚至不喜欢加起来是完全平方数的两个数。

今天,他想从 1 到 100 中选择一些数组成一个集合,要求不选择任何一个完全平方数,集合中任意两个数相加也不能是完全平方数。请问,小明最多能选出多少个数。

题解:

dfs+最优化剪枝

剪枝主要就是有一个预测值maybe,就是假如没被标记的数都可以选上的最优情况下贡献的cnt都没有已经存在的ans大的话,就可以return了,可以剪掉很大一部分的枝节!

还有一个就是完全平方数得预处理到200以内,因为99+98差不多就在这个范围内,不能只预处理到100

关于预测数maybe的处理出了点问题,导致我卡了超级久超级久,下一次一定要再细心一点!!

Code:
#include <bits/stdcpp.h>
using namespace std;
#define ioss ios::sync_with_stdio(false);cin.tie(NULL);cout.tie(NULL);
int a[20];
bool bj[1010];
int ans;
void dfs(int now,int cnt,int bg,int maybe){
    if(a[bg]-now<=now)bg++;
    if(cnt>ans) ans=cnt;
    if(now==100)return;
    if(cnt+maybe<=ans)return;
    if(!bj[now]){
        int t[20],tn=0;
        for(int i=bg;i<=16;++i){
            if(a[i]-now>=100)break;
            if(!bj[a[i]-now]){
                t[++tn]=a[i]-now;
                bj[a[i]-now]=1;
            }
        }
        maybe-=tn;
        dfs(now+1,cnt+1,bg,maybe-1);
        maybe+=tn;
        for(int i=1;i<=tn;++i){
            bj[t[i]]=0;
        }
    }
    if(!bj[now])  
        dfs(now+1,cnt,bg,maybe-1);
    else
        dfs(now+1,cnt,bg,maybe);
    //这个地方卡了超级久!!!如果这个点本来就是被标记过的,那么maybe就不需要再减1了,因为之前标记的时候就已经减过了,再减就减多了,跑出来一直不对
}
int main(){
    for(int i=1;i<=16;++i){
        a[i]=i*i;
        bj[a[i]]=1;
    }
    dfs(2,0,3,90);
    cout<<ans; //36
    return 0;
}
  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值