目标:200道题,菜鸡如我…
文章目录
- 1、DFS
- 2、BFS
- 3、DP
- 4、图论
- 1、AcWing 849. Dijkstra求最短路 I ([AcWing](https://www.acwing.com/activity/content/problem/content/918/1/))
- 2、850. Dijkstra求最短路 II (AcWing850)堆优化
- 3、853. 有边数限制的最短路([AcWing853](https://www.acwing.com/problem/content/855/)) Bellman-ford
- 4、851.spfa求最短路([AcWing](https://www.acwing.com/problem/content/853/))
- 5、852. spfa判断负环([AcWing](852. spfa判断负环))
- 6、854. Floyd求最短路([AcWing](https://www.acwing.com/problem/content/856/))
- 5、贪心
- 1、 柠檬水找零([LeetCode 860](https://leetcode.com/problems/lemonade-change/description/))
- 2、 判断子序列([LeetCode 392](https://leetcode-cn.com/problems/is-subsequence/description/))
- 3、 分发饼干([LeetCode 455](https://leetcode-cn.com/problems/assign-cookies/description/))
- 4、 跳跃游戏([LeetCode 55](https://leetcode-cn.com/problems/jump-game/description/))
- 5、 跳跃游戏II([LeetCode 45](https://leetcode-cn.com/problems/jump-game-ii/description/))
- 6、 摆动序列([LeetCode 376](https://leetcode-cn.com/problems/wiggle-subsequence/description/))
- 7、根据身高重建队列([LeetCode 406](https://leetcode-cn.com/problems/queue-reconstruction-by-height/description/))
- 8、用最少数量的箭引爆气球([LeetCode 452](https://leetcode-cn.com/problems/minimum-number-of-arrows-to-burst-balloons/))
- 9、移掉K位数字([LeetCode 402](https://leetcode-cn.com/problems/remove-k-digits/description/))
- 10、加油站([LeetCode 134](https://leetcode-cn.com/problems/gas-station/))
- 11、区间选点([AcWing 905](https://www.acwing.com/problem/content/907/))
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;
}