蓝桥杯省赛准备---刷题整理

目标:200道题,菜鸡如我…

文章目录

1、DFS

1、 递归实现指数型枚举 (Acwing 92)
#include <iostream>

using namespace std;

int n;

void dfs(int u, int state)
{
    if(u == n) {
        for(int i=0;i<n;i++){
            if(state>>i & 1)
                printf("%d ", i+1);
            
        }
        printf("\n");
        return;
    }
    dfs(u+1, state);
    dfs(u+1, state + (1<<u) );
}

int main()
{
    scanf("%d", &n);
    
    dfs(0,0);
    
    return 0;
}
3、递归实现排列型枚举 (AcWing 94)
#include <iostream>
#include <vector>
using namespace std;
int n;

void dfs(vector<int> path, int u, vector<bool> vis)
{
    if(u == n) {
        for(int i = 0;i < n; i ++ )
            printf("%d ", path[i]);
        printf("\n");
        return;
    }
    
    for(int i = 1;i<=n;i++) // 枚举每个位置放哪个数
    {
        if(!vis[i]) {
            path.push_back(i);
            vis[i] = true;
            dfs(path, u+1, vis);
            vis[i] = false;
            path.pop_back();
        }
    }
    
    
    
    
}
int main()
{
    vector<int> path;
    vector<bool> vis(10, false);
    
    scanf("%d", &n);
    
    dfs(path, 0, vis);
    
    return 0;
}
4、N-皇后问题 (AcWing843
#include <iostream>

using namespace std;

const int N = 10;

int n;
char g[N][N];
bool col[N], dg[N], udg[N];

void dfs(int u)
{
    if(u == n) {
        for(int i=0;i<n;i++) puts(g[i]);
        puts("");
        return;
    }
    
    for(int i=0;i<n;i++)
    {
        if(!col[i] && !dg[u + i] && !udg[n - u + i]) 
        {
            col[i] = dg[u + i] = udg[n - u + i] = true;
            g[u][i] = 'Q';
            dfs(u+1);
            g[u][i] = '.';
            col[i] = dg[u + i] = udg[n - u + i] = false;
        }
    }
}

int main()
{
    cin>>n;
    for(int i=0;i<n;i++)
        for(int j = 0;j<n;j++)
            g[i][j] = '.';
    dfs(0);
    
    
    return 0;
}

2、BFS

1、走迷宫(AcWing844
#include <iostream>
#include <queue>
#include <algorithm>

using namespace std;

typedef pair<int, int> PII;
const int N = 150;
int g[N][N], d[N][N];
int m, n;

int bfs()
{
    queue<PII> q;
    fill(d[0],d[0]+N*N, -1);
    q.push({0,0});
    d[0][0] = 0;
    int dx[4] = {-1,0,1,0}, dy[4] = {0,1,0,-1};
    
    
    
    while(q.size())
    {
        auto t = q.front();
        q.pop();
        
        
        for(int i=0;i<4;i++)
        {
            int x = t.first+dx[i];
            int y = t.second + dy[i];
            if(x>=0 && x<m && y>=0 && y<n && d[x][y] == -1 && g[x][y] == 0)
            {
                d[x][y] = d[t.first][t.second] + 1;
                q.push({x,y});
            }
        }
    }
    return d[m-1][n-1];
}

int main()
{
    
    scanf("%d%d", &m, &n);
    
    for(int i=0;i<m;i++)
        for(int j=0;j<n;j++)
            scanf("%d", &g[i][j]);
    //printf("%d", bfs());
    cout<<bfs()<<endl;
    return 0;
}

2、被围绕的区域(Leetcode130

逆向考虑问题,我们先统计出哪些区域不会被攻占,然后将其它区域都变成’X’即可。
具体做法如下:
开一个二维布尔数组,记录哪些区域被遍历过。
枚举所有边界上的’O’,从该位置做Flood Fill,即做深度优先遍历,只遍历是’O’的位置,并将所有遍历到的位置都标记成true。
将所有未遍历到的位置变成’X’。
时间复杂度分析:每个位置仅被遍历一次,所以时间复杂度是 O(n2)O(n2),其中 nn 是地图的边长。

class Solution {
public:
    vector<vector<bool>> st;
    int n, m;

    void solve(vector<vector<char>>& board) {
        if(board.empty() || board[0].empty()) return;

        n = board.size(), m = board[0].size();  
        st = vector<vector<bool>> (n,vector<bool>(m, false));  
        
        for(int i=0;i<n;i++){
            if(board[i][0] == 'O') dfs(i,0,board);
            if(board[i][m-1] == 'O') dfs(i,m-1,board);
        }
        for(int i=0;i<m;i++){
            if(board[0][i] == 'O') dfs(0,i,board);
            if(board[n-1][i] == 'O') dfs(n-1,i,board);
        }

        for(int i=0;i<n;i++)
            for(int j=0;j<m;j++)
                if(!st[i][j])
                    board[i][j] = 'X';

    }

    void dfs(int x, int y, vector<vector<char>>& board)
    {
        st[x][y] = true;
        int dx[4] = {-1,0,1,0}, dy[4] = {0,1,0,-1};
        for(int j = 0;j<4;j++)
        {
            int a = x+dx[j], b = y + dy[j];
            if(a>=0 && a<n && b>=0 && b<m && !st[a][b] && board[a][b] == 'O')
                dfs(a,b,board);
        }
    }
};

3、DP

1、Maximum Subsequence Sum(PAT
#include<iostream>
#include<algorithm>
using namespace std;

const int N = 10010;

int main()
{
    int n;
    cin>>n;
    int a[N], s[N]; //s[i] 表示产生dp[i]的连续子序列的从a中哪一个元素开始
    for(int i=1;i<=n;i++) {
        cin>>a[i];
        
    }
    int dp[N];
    dp[0] = 0;
    bool f = false;
    for(int i=1;i<=n;i++)
        if(a[i]>=0) f = true;

    if(f == false) {
        cout<<"0 "<<a[1]<<" "<<a[n]<<endl;
        return 0;
    }

    for(int i=1;i<=n;i++)
    {
        //dp[i] = max(a[i], dp[i-1]+a[i]); 
        if(dp[i-1]+a[i] > a[i]){
            dp[i] = dp[i-1] +a[i];
            s[i] = s[i-1];
        }else{
            dp[i] = a[i];
            s[i] = i;
        }
    }
    int k =0;
    for(int i =1;i<=n;i++)
        if(dp[i]>dp[k])
            k = i;

    cout<<dp[k]<<" "<<a[s[k]]<<" "<<a[k]<<endl;


    return 0;
}

4、图论

1、AcWing 849. Dijkstra求最短路 I (AcWing
#include <iostream>
#include <algorithm>
using namespace std;

const int N = 505, INF = 1e9;
int g[N][N], d[N], n;
bool vis[N] = {false};

void Dijkstra(int s)
{
    fill(d,d+N,INF);
    d[s] = 0;
    for(int i = 1;i <= n;i ++ )
    {
        int u = -1;
        for(int j=1;j<=n;j++) {
            if(!vis[j] && (u == -1 || d[u] > d[j]))
                u = j;
        }
        vis[u] = true;
        for(int v=1;v<=n;v++) {
            d[v] = min(d[v], d[u]+g[u][v]);
        }
        
    }
}

int main()
{
    int m;
    scanf("%d%d",&n,&m);
    
    fill(g[0], g[0] + N * N, INF);
    
    for(int i=0;i<m;i++)
    {
        int x,y,z;
        scanf("%d%d%d",&x,&y,&z);
        if(g[x][y] != INF && g[x][y] > z)
            g[x][y] = z;
        else if(g[x][y] == INF)
            g[x][y] = z;
        
    }
    
    Dijkstra(1);
    
    if(d[n] == INF) cout<<"-1"<<endl;
    else cout<<d[n]<<endl;
    
    
    
    return 0;
}
2、850. Dijkstra求最短路 II (AcWing850)堆优化
#include <iostream>
#include <queue>
#include <vector>
#include <cstdio>

using namespace std;
typedef pair<int, int> PII;
struct Node {
    int v, w;
    Node():v(), w(){}
    Node(int _v, int _w):v(_v), w(_w){}
};
const int N = 100010;
const int INF = 1e9;
vector<Node> g[N];
bool st[N];
int d[N];

void dijkstra(int s)
{
    fill(d, d+N, INF);
    d[s] = 0;
    priority_queue<PII,vector<PII>, greater<PII>> heap;
    heap.push({0,1});
    while(heap.size())
    {
        auto t = heap.top();
        heap.pop();
        
        int ver = t.second, dis = t.first;
        if(st[ver]) continue;
        st[ver] = true;
        
        for(int j=0;j<g[ver].size();j++)
        {
            int v = g[ver][j].v;
            if(st[v] == false && dis + g[ver][j].w < d[v])
            {
                d[v] = dis + g[ver][j].w;
                heap.push({d[v], v});    
            }
                
        }
    }
}

int main()
{
    int n, m;
    scanf("%d%d", &n, &m);
    for(int i=0;i<m;i++){
        int x,y,z;
        scanf("%d%d%d", &x,&y,&z);
        g[x].push_back(Node(y,z)); // add edge
    }   
    dijkstra(1);
    if(d[n]!=INF) cout<<d[n]<<endl;
    else cout<<"-1"<<endl;
    return 0;
}
3、853. 有边数限制的最短路(AcWing853) Bellman-ford
#include <iostream>
#include <cstring>
#include <algorithm>

using namespace std;
const int M = 10010;
const int N = 550;
int n, m, k;
int d[N], backup[N];
const int INF = 1e9;
struct Edge
{
    int a, b, w;
}edges[M];

int bel()
{
    fill(d, d+N, INF);
    d[1] = 0;
    for(int i=0;i<k;i++)
    {
        memcpy(backup, d, sizeof d);
        for(int j=0;j<m;j++)
        {
            int a = edges[j].a, b = edges[j].b, w = edges[j].w;
            d[b] = min(d[b], backup[a]+w);
        }
    }
    if(d[n] > INF / 2) return -1;
    else return d[n];
}

int main()
{
    scanf("%d%d%d", &n, &m, &k);
    for(int i=0;i<m;i++)
    {
        int a, b, c;
        scanf("%d%d%d", &a, &b, &c);
        edges[i] = {a,b,c};
    }
    int t = bel();
    if(t == -1) cout<<"impossible";
    else cout<<t<<endl;
    
    
    return 0;
}
4、851.spfa求最短路(AcWing
#include <iostream>
#include <queue>
#include <cstring>
using namespace std;
const int N = 1e5+10;
int h[N], e[N], w[N], ne[N], idx;
int n, m;
int d[N];
bool st[N];
const int INF = 1e9;

void add(int a, int b, int c)
{
    e[idx] = b, w[idx] = c, ne[idx] = h[a], h[a] = idx ++;
}

int spfa()
{
    
    fill(d,d+N,INF);
    d[1] = 0;
    queue<int> q;
    q.push(1);
    st[1] = true;
    while(q.size())
    {
        int t = q.front();
        q.pop();
        st[t] = false;
        for(int i=h[t]; i!=-1; i=ne[i])
        {
            int j = e[i];
            if(d[t]+w[i] < d[j])
            {
                d[j] = d[t] + w[i];
                if(!st[j])
                {
                    q.push(j);
                    st[j] = true;
                }
            }
        }
    }
    if(d[n] >= INF / 2) return -1;
    else return d[n];
}

int main()
{
    std::ios::sync_with_stdio(false);
    //memset(h, -1, sizeof h);
    fill(h,h+N,-1);
    cin>>n>>m;
    for(int i=0;i<m;i++)
    {
        int x, y, z;
        cin>>x>>y>>z;
        add(x,y,z);
    }
    int t = spfa();
    
    if(t == -1) cout<<"impossible";
    else cout<<t<<endl;
    
    return 0;
}
5、852. spfa判断负环([AcWing](852. spfa判断负环))
#include <iostream>
#include <queue>
#include <cstring>
using namespace std;
const int inf = 1e9;
const int N = 2010, M = 10010;;
int n,m;
int h[N], e[M], ne[M], w[M], idx;
bool st[N];
int cnt[N], d[N];

void add(int a,int b, int c)
{
    e[idx] = b, ne[idx] = h[a], w[idx] = c, h[a] = idx ++ ;
}

bool spfa()
{
    memset(d,inf,sizeof d);
    d[1] = 0;
    queue<int> q;
    
    
    for(int i=1;i<=n;i++)
    {
       
        st[i] = true;
        q.push(i);
    }
    
    while(q.size())
    {
        int t = q.front();
        q.pop();
        st[t] = false;
        
        for(int i=h[t]; i!=-1; i = ne[i])
        {
            int j = e[i];
            if(d[t]+w[i]<d[j])
            {
                d[j] = d[t]+w[i];
                cnt[j] = cnt[t] + 1;
                if(cnt[j] >= n) return true;
                if(!st[j])
                {
                    q.push(j);
                    st[j] = true;
                }
            }
        }
    }
    
    return false;
}

int main()
{
    ios::sync_with_stdio(false);
    fill(h,h+N,-1);
    cin>>n>>m;
    for(int i=0;i<m;i++)
    {
        int x, y, z;
        cin>>x>>y>>z;
        add(x,y,z);
    }
    
    if(spfa()) cout<<"Yes"<<endl;
    else cout<<"No"<<endl;
    
    return 0;
}
6、854. Floyd求最短路(AcWing
#include <iostream>
#include <algorithm>

using namespace std;
const int N = 220;
const int INF = 1e9;
int d[N][N];
int n,m,k;

void f()
{
    for(int i=1;i<=n;i++)
        for(int j=1;j<=n;j++)
            for(int t =1;t<=n;t++)
                if(d[j][i]!=INF&&d[i][t]!=INF&&d[j][i]+d[i][t]<d[j][t])
                    d[j][t] = d[j][i]+d[i][t];
}

int main()
{
    scanf("%d%d%d", &n, &m, &k);
    fill(d[0],d[0]+N*N,INF);
    //for(int i=1;i<=n;i++)
    //    for(int j=1;j<=n;j++)
    //        if(i == j) d[i][j] = 0;
    //        else d[i][j] = INF;
    for(int i=1;i<=n;i++) d[i][i] = 0;
    
    for(int i=0;i<m;i++)
    {
        int x, y, z;
        scanf("%d%d%d", &x, &y, &z);
        d[x][y] = min(d[x][y], z);
    }
    f();
    for(int i=0;i<k;i++)
    {
        int x, y;
        scanf("%d%d", &x, &y);
        if(d[x][y]!=INF) printf("%d\n", d[x][y]);
        else printf("impossible\n");
    }
    return 0;
}

5、贪心

1、 柠檬水找零(LeetCode 860
2、 判断子序列(LeetCode 392
3、 分发饼干(LeetCode 455
4、 跳跃游戏(LeetCode 55
5、 跳跃游戏II(LeetCode 45
6、 摆动序列(LeetCode 376
7、根据身高重建队列(LeetCode 406
8、用最少数量的箭引爆气球(LeetCode 452
9、移掉K位数字(LeetCode 402
10、加油站(LeetCode 134
11、区间选点(AcWing 905
  • 25
    点赞
  • 231
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值