Point1 贪心算法
Point2 关于>>的代码
Point3 二叉树
“中序遍历+先序遍历”,能确定一棵树。
“中序遍历+后序遍历”,能确定一棵树。
“先序遍历+后序遍历”,不能确定一棵树。
Point4 二叉堆
Point5 全排列
Point6 广度优先搜索基本模板
NO.1
题目描述:
题意分析:三国中的n个武将之间两两之间都有一个默契值。你和机器人需要进行轮流选角,最后选完以后,派出所选的队伍里默契值最大的两个武将出战,比较双方的默契值哪个更大。
解题思路:你每次选一个,计算机会把你选的那个角色对应的最佳搭档给选了。也就是说你无法获得这个角色的最佳搭档,但其实,计算机也无法获得他选的角色的最佳搭档。所以这一个组合相当于废了然后你接下来选的角色,只需要是上一个角色的次佳搭档即可。我们假设,计算机接下来会把你选的次佳搭档中剩余的最佳搭档给选了,但其实这个角色(真正的最佳搭档)已经被你第一次给选了。所以无论如何你都是必赢的那么接下来只需要找每一个角色的次佳搭档是多少,然后找最大的那一对即可
复杂度分析:O(n)
带注释的代码:
#include<iostream>
#include<cstdio>
#include<algorithm>
using namespace std;
int a[505][505];//用二维数组来储存
int main(){
int n;
scanf("%d",&n);
for(int i=1;i<n;i++){
for(int j=i+1;j<=n;j++){
scanf("%d",&a[i][j]);
a[j][i]=a[i][j];//小涵和计算机选的武将是对称的
}
}
int ans=0;//初始化答案
for(int i=1;i<=n;i++){
sort(a[i]+1,a[i]+1+n);//将默契值从小到大排序
if(a[i][n-1]>ans){
ans=a[i][n-1];//选出次佳搭档中最大的那个
}
}
printf("1\n%d\n",ans);//一定有解,即小涵一定会赢
return 0;
}
NO.2
题目描述:
题意分析:
解题思路:
复杂度分析:
带注释的代码:
NO.3
题目描述:
#include<bits/stdc++.h>
using namespace std;
const int N = 2e6 + 10;
const int mod = 100003;
map<string, int> mp;
int a[N];
int n, m;
int ans;
int check(int x){
for(int i = 2; i * i <= x; i++){
if(x % i == 0){
return 0;
}
}
return 1;
}
void dfs(int k, int p, int sum){
//k表示选了几个数
//p表示从第几个数开始选,为了防止重复选择
//sum表示选的数字的和
if(k == m){
ans += check(sum);
return ;
}
if(k + n - p + 1 < m){
//剩下的数字不够选,直接return
return ;
}
for(int i = p; i <= n; i++){
dfs(k + 1, i + 1, sum + a[i]);
}
}
int main(){
cin >> n >> m;
for(int i = 1; i <= n; i++){
cin >> a[i];
}
dfs(0, 1, 0);
cout << ans << '\n';
return 0;
}
NO.4
题目描述:
题意分析:有一个 n*m 的棋盘,在某个点 (x, y)上有一个马,要求你计算出马到达棋盘上任意一个点最少要走几步。输入格式 输入只有一行四个整数,分别为 n, m, x, y。输出格式 一个 n *m 的矩阵,代表马到达某个点最少要走几步(不能到达则输出 -1。
解题思路:数据规模与约定对于全部的测试点,保证 1 <=x <=n<=400,1<= y <=m <=400。思路: 广搜,但是要注意的是国际象棋中马的走法:每步棋先横走或直走一格,然后再往外斜走一格。所以有8种方向可以走:3 3 1 10 3 2 3 -1 1 2 1 4,然后在每个节点都记录一下当前已经走了几步,最后挨个输出就行,由于标记了是否走过,避免了重复走的情况,所以step记录的值都是最少的步骤,就达到了记录最小步数的目的。
带注释的代码:
#include<bits/stdc++.h>
using namespace std;
int n,m;
int dir[][2]={{-1,-2},{-2,-1},{-2,1},{-1,2},{1,2},{2,1},{2,-1},{1,-2}};
struct pos{
int r,c,d;
pos(int a=0,int b=0,int d=0):r(a),c(b),d(d){}
};
int mp[405][405];
void bfs(int r,int c);
int main(){
int sr,sc;
cin>>n>>m>>sr>>sc;
memset(mp,-1,sizeof mp);
bfs(sr,sc);
for(int i=1;i<=n;i++){
for(int j=1;j<=m;j++){
cout<<mp[i][j]<<'\t';
}
cout<<endl;
}
return 0;
}
void bfs(int r,int c){
queue<pos>q;
q.push(pos(r,c));
mp[r][c]=0;
while(!q.empty()){
pos p=q.front();
q.pop();
for(int i=0;i<8;i++){
int nr=p.r+dir[i][0];
int nc=p.c+dir[i][1];
int nd=p.d+1;
if(nr>=1&&nr<=n&&nc>=1&&nc<=m&&mp[nr][nc]==-1){
mp[nr][nc]=nd;
q.push(pos(nr,nc,nd));
}
}
}
}
NO.5
题目描述:
题意分析:在 3×33×3 的棋盘上,摆有八个棋子,每个棋子上标有 11 至 88 的某一数字。棋盘中留有一个空格,空格用 00 来表示。空格周围的棋子可以移到空格中。要求解的问题是:给出一种初始布局(初始状态)和目标布局(为了使题目简单,设目标状态为 123804765123804765),找到一种最少步骤的移动方法,实现从初始布局到目标布局的转变。
带注释的代码:
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
inline ll read() {
ll f = 1, x = 0; char ch;
do {ch = getchar(); if (ch == '-')f = -1;} while (ch > '9' || ch < '0');
do {x = x * 10 + ch - '0'; ch = getchar();} while (ch >= '0' && ch <= '9');
return f * x;
}
char s[15];
char goal[] = {'1', '2', '3', '8', '0', '4', '7', '6', '5'};
int maxdepth;
inline int h(char *cur) {
int res = 0;
for (int i = 0; i < 9; i ++ ) {
if (goal[i] != cur[i] && cur[i] != 0) res++;
}
return res;
}
int dx[] = {0, 1, -1, 0};
int dy[] = {1, 0, 0, -1};
bool dfs (int depth, char *a, int pre) {
if (h(a) == 0) return true;
if (depth + h(a) - 1 > maxdepth) return false;
int sx, sy;
for (int i = 0; i < 9; i ++ )
if (a[i] == '0') sx = i / 3 + 1, sy = i % 3 + 1;
for (int i = 0; i < 4; i ++ ) {
int xx = dx[i] + sx, yy = dy[i] + sy;
if (xx < 1 || xx > 3 || yy < 1 || yy > 3 || (pre + i == 3)) continue;
swap(a[(xx - 1) * 3 + yy - 1], a[(sx - 1) * 3 + sy - 1]);
if (dfs(depth + 1, a, i)) return true;
swap(a[(xx - 1) * 3 + yy - 1], a[(sx - 1) * 3 + sy - 1]);
}
return false;
}
int main() {
scanf ("%s", s);
if (h(s) == 0) {puts("0"); return 0;}
for (maxdepth = 1; ; maxdepth ++ ) {
if (dfs(0, s, -1)) {
printf ("%d\n", maxdepth);
return 0;
}
}
return 0;
}