2017-9-26离线赛总结

失分小结:

估分:260
实际分数:200
评价:第二题看错了qwq,第一题人家暴力也过了。。。

知识漏洞

考试过程:
第一题先是打了个暴力然后感觉可能被卡掉
但不管它,先写第二题
第二题看都没看直接上模拟
在用树遍历一下输出
这时考试过去一小时

然后模拟第三题
整体上还是不错的
17分钟30分
45分钟60分

这时离考试结束还有105分钟

然后自以为260到手

仔细思考了一下第一题,自以为原来的解会被卡掉,极限数据1.012ms
于是乎想出了正解,然后调了50分钟。。。

题解: 第一题:二维前缀和直接上

第二题:

题目描述 BSOI 在线评测机被不明身份的人入侵了!!系统中大量的数据遭到恶意破坏,数据文件残缺不全。现在,老师正在尽力抢救数据文件。为了检查数据文件是否完整,老师打印出了所有文件的列表,但数据文件太多,老师眼睛都要看花了。所以,为了方便老师检查,需要你写个程序处理一下文件列表,转换成下面这样统一的格式:
这里写图片描述
生成的列表格式有如下要求:
1.属于同一层的文件或文件夹位于相同的缩进处,相邻两层文件间差距 5 个字符;
2.每个文件夹或文件前有 4 个’-‘(根目录除外),文件夹下方属于文件夹的部分有’|’;
3.属于统一文件夹下的文件或子文件夹按字典序排列;
输入 第一行一个整数 n(n<=50) ,表示总共的文件数目; 接下来 n 行,每行描述一个文件的路径,路径以’/’作为文件分隔符;
所有文件(及文件夹)名均由小写字母和英文点组成; 所有输入的根目录都是一样的, 文件名长度不超过 10 个字符, 每个文件夹下不超过
15个文件,不超过 5 层。
输出 输出符合要求的文件列表
这里写图片描述

思路
原来以为是都不会重复的,然后就直接遍历判是否重复就好了
但题目描述是文件名可能会有重复
那么其实也有很多方法判断(如map)
或者直接dfs分割出子文件(lzm的写法)

但有种特别方便的玄学写法(cy神犇)

将一个数据进行如下分割
data/666/yzk
->data
->data/666
->data/666/yzk

可以发现上述字符串的字典序即是这样
一个文件的文件夹必定出现在这个文件的上方
那么把所有的数据像如上方法分割
然后排序
把最后一个斜杠后的部分输出

#include<bits/stdc++.h>
using namespace std;
#define FOR(i,a,b) for(int i=(a);i<=(b);i++)
#define DOR(i,a,b) for(int i=(a);i>=(b);i--)
#define M 10005
string s[M];
int main(){
    int n;
    cin>>n;
    int m=n;
    FOR(i,1,n)cin>>s[i];
    FOR(i,1,n){
        int l=s[i].length();//分离文件名及文件夹名 
        FOR(j,0,l-1)if(s[i][j]=='/')s[++m]=s[i].substr(0,j);
    }
    sort(s+1,s+m+1);
    n=0;
    FOR(i,1,m)//去重 
        if(s[i]!=s[i-1]) s[++n]=s[i];   
    cout<<s[1]<<endl;
    FOR(i,2,n){
        int l=s[i].length(),cnt=0,x;
        FOR(j,0,l-1)if(s[i][j]=='/')cnt++,x=j;    
        FOR(j,1,cnt-1) printf("|    ");
        printf("|----");
        FOR(j,x+1,l-1)printf("%c",s[i][j]);
        puts("");
    }
    return 0;   
}

第三题:

题目描述 给定一个n*m的地图和蛇的初始位置,地图中有些位置有石头,蛇不能经过。当然蛇也不能爬到地图之外。
每次移动,蛇头先动,接下来每节身体到达上一节身体所在的位置。蛇头将要去的地方,不能有身体的其他部分。
求蛇最少移动多少步到达(1,1)点。
下图B1是蛇头,B4是蛇尾,第二幅图是第一幅图蛇移动一步的效果,黑色区域是蛇头。
这里写图片描述
输入 第一行3个整数n、m、K,K表示蛇的长度。
接下来K行,每行两个整数,表示蛇每节身体的坐标,依次从蛇头到蛇蛇尾,坐标为行号和列号。
第K+2行一个整数s,表示石头的个数。
接下来s行,每行两个整数,表示一个石头的行号和列号。石头不会出现在(1,1)。
输出输出蛇头最少多少步,可以到达(1,1)点。如果无法到达,输出-1。
对于100%的数据,1≤K≤8,n和m的范围[2,20];

思路:
这题数据很弱,怎么瞎搞都可以AC
这里还是给出正经解法(跑得比错误解法还要慢-_-|||):

这题一看就是道纯模拟题
求最小步数,果断bfs解
但难点是蛇的长度为8时记录坐标果断是不行的

根据蛇是连续的这一常识
一个图中有很多种情况都是不可能的
我们可以记录蛇的上一节与下一节的位置关系(共有四种)还有蛇头的坐标
这样空间复杂的大约为20*20*(4^7)=6700000+

#include<bits/stdc++.h>
using namespace std;
#define FOR(i,x,y) for(int i=(x);i<=(y);i++)
int n,m,k;
int X[8],Y[8],O[8];
int cx[4]= {0,1,0,-1},cy[4]= {1,0,-1,0};
bool chk(int x,int y) {return (x>0&&x<=n&&y>0&&y<=m);}
bool mark[21][21],mark1[7000000];
struct node {int O[8],step,x,y;};
queue<node>q;
int Hash(int A[],int x,int y) {
    int res=(x-1)*20+y-1;
    FOR(i,1,k-1) {
        res=res*4+A[i];
    }
    return res;
}
int bfs(int x,int y) {
    node t;t.x=x,t.y=y,t.step=0;
    FOR(i,1,k-1)t.O[i]=O[i];
    q.push(t);
    mark1[Hash(t.O,x,y)]=1;
    if(t.x==1&&t.y==1)return 0;
    while(!q.empty()) {
        node now=q.front();
        q.pop();
        FOR(j,0,3) {
            node nxt;nxt.step=now.step+1;nxt.x=now.x+cx[j];nxt.y=now.y+cy[j];
            if(!chk(nxt.x,nxt.y))continue;
            nxt.O[1]=j;
            FOR(i,2,k-1)nxt.O[i]=now.O[i-1];
            if(mark[nxt.x][nxt.y]||mark1[Hash(nxt.O,nxt.x,nxt.y)])continue;
            mark1[Hash(nxt.O,nxt.x,nxt.y)]=1;
            int x=now.x,y=now.y;
            bool flag=0;
            FOR(i,1,k-1){
                x-=cx[now.O[i]],y-=cy[now.O[i]];
                if(nxt.x==x&&nxt.y==y){flag=1;break;}
            }
            if(flag)continue;
            if(nxt.x==1&&nxt.y==1)return nxt.step;
            q.push(nxt);
        }
    }
    return -1;
}
int main() {
    cin>>n>>m>>k;
    int s,a,b;
    FOR(i,0,k-1) {
        scanf("%d%d",&X[i],&Y[i]);
        if(i!=0) {
            if(X[i]==X[i-1]&&Y[i]+1==Y[i-1])O[i]=0;
            else if(X[i]+1==X[i-1]&&Y[i]==Y[i-1])O[i]=1;
            else if(X[i]==X[i-1]&&Y[i]-1==Y[i-1])O[i]=2;
            else O[i]=3;
        }
    }
    scanf("%d",&s);
    FOR(i,1,s) {
        scanf("%d %d",&a,&b);
        mark[a][b]=1;
    }
    printf("%d\n",bfs(X[0],Y[0]));
    return 0;
}
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值