欢迎光临散文网 会员登陆 & 注册

2021_7_23 acm训练部分心得

2021-07-23 13:04 作者:外号不可能是老眯  | 我要投稿

1点下训总结一下前两天学的部分。

牛客UCF Local Programming Contest Round 1A C题

题目:

就是给一窜数让你求没有重复元素的子序列之和

代码:C(web1)

#include<bits/stdc++.h>

using namespace std;

long long n, t, a, lt, rt, ans;

map<long long, int>pos, cnt;

int main()

{

cin >> n;

for(rt; rt < n; rt++)

{

cin >> a;

if(cnt[a]++)

lt=max(lt, pos[a]+1LL);

pos[a]=rt;ans+=rt-lt+1;

}

cout << ans;

}


这题大概思路就是从最后开始向前数,碰到第一个重复及停止,转换为程序大概的意思是,如果n个元素没有重复则为n+(n-1)+(n-2)........+1,那么现在有重复了如何?那么就以在此点的n0减去重复前的个数及代码中的rt-lt因为是从零开始,所以+1及:rt-lt+1。其中rt是元素原本位置lt是碰到第一个重复的数。

那么 如何标出第一个重复的数呢?map——pos, cnt;当输入的a时cnt【a】++这个的意思表示a出现的次数,如何已经出现了那么就让lt于pos【a】+1比较选大,该怎么解释呢。。。pos【a】是储存最后一次出现的相同元素的位置的map。

比如1 2 2 4 3 5

1(0)第一次出现 pos1= 0

2(1)第一次出现 pos2= 1

2 (2)第二次出现 pos2(1+1)与lt(0)比较 lt=1+1 ,pos2=2,所以之后每一个元素到2位置结束前面两个元素不用管当2-1此位置那么之后比有2的重复。

而max的比较意义是找出最近那个相同 比如 1  2 1 0 2 1

之后求和输出(比赛时只做出了两题最简单的那种但是还是得了个三等奖)


知识:1 #include<bits/stdc++.h>包括了很多就不用打一大串include了

           2 map<long long, int>pos, cnt; map表示一个字典 前一个是key 后一个参数是value,类型可自己定义,无需声明大小,key是唯一的,后面两给 pos cnt 是变量。可以生成模板多次使用,方法到时百度。


2 牛客50题中第一题

bfs

代码:

#include<bits/stdc++.h>//0->A 1->B

using namespace std;

const int dx[]={1,0,-1,0,1,1,-1,-1};

const int dy[]={0,1,0,-1,1,-1,1,-1};

int n,m;

char a[1005][1005];

bool vis[2][1005][1005];

struct node{

    int x,y;

};

queue<node> q[2];

//

bool check_bfs(int w){

    int Size=q[w].size();

    while(Size--){

        int x=q[w].front().x;

        int y=q[w].front().y;

        q[w].pop();

        for(int k=0;k<(w?4:8);k++){

            int tx=x+dx[k];

            int ty=y+dy[k];

            if(tx<1 || tx>n || ty<1 || ty>m || a[tx][ty]=='#' || vis[w][tx][ty]) continue;

            if(vis[!w][tx][ty]) return true;

            q[w].push((node){tx,ty});

            vis[w][tx][ty]=1;

        }

    }

    return false;

}

int main(){

    cin>>n>>m;

    for(int i=1;i<=n;i++){

        for(int j=1;j<=m;j++){

            cin>>a[i][j];

            if(a[i][j]=='C'){

                q[0].push((node){i,j});

                vis[0][i][j]=1;

            }

            if(a[i][j]=='D'){

                q[1].push((node){i,j});

                vis[1][i][j]=1;

            }

        }

    }

    int tim=0;

    bool flag=false;

    while(q[0].size() || q[1].size()){

        flag=false;

        tim++;

        if(q[0].size() && check_bfs(0)){

            flag=true;

            break;

        }

        if(q[1].size() && check_bfs(1)){

            flag=true;

            break;

        }

        if(q[1].size() && check_bfs(1)){

            flag=true;

            break;

        }

    }

    if(flag){

        puts("YES");

        cout<<tim<<'\n';

    }

    else{

        puts("NO");

    }

    return 0;

}


因为是求步数,所以用的是BFS,BFS是广度优先遍历把第一给放进队列弹出来,然后压入第一个弹出来的周围的链接的路。每次循环tim+1;然后代码写得很漂亮,  vis[1][i][j]=1;0,1分别表示两个点是否走过,如果碰到走过路径立即结束,遍历完都没有碰到就no,下训了,干饭了。

知识点:

queue<node> q[2];

push(x) 将x压入队列的末端

pop() 弹出队列的第一个元素(队顶元素),注意此函数并不返回任何值

front() 返回第一个元素(队顶元素)

back() 返回最后被压入的元素(队尾元素)

empty() 当队列为空时,返回true

size() 返回队列的长度


代码例子:

1.#include <iostream>

2.#include <queue>

3.using namespace std;

4.int main()

5.{

6. int n,k;

7. cin>>n>>k;

8. int num=1;

9. queue<int> list;

10. for(int i=1;i<=n;i++)

11. list.push(i);

12. while(list.size()>1)

13. {

14. int a=list.front();

15. list.pop();

16. if(num%k!=0&&num%10!=k)

17. {

18. list.push(a);

19. }

20. num++;

21. }

22. cout<<list.front()<<endl;

23. return 0;

24.}


2021_7_23 acm训练部分心得的评论 (共 条)

分享到微博请遵守国家法律