目录
7-13 是否完全二叉搜索树(30)二叉搜索树 + 完全二叉树层序遍历
7-14 直捣黄龙(30)Dijkstra(路径+各种数组)+ unordered_map
7-1 正整数A+B (15)
A和B中间可能会有大于一个空格,除第一个空格外的空格属于B,cin俩个string字符串不可行
也可使用stio函数进行优化将字符串直接转化成数字,还要手动判断两数的范围
#include<bits/stdc++.h>
using namespace std;
int n;
string a,b;
int x=0,y=0;
int chang(string s){
int t=0;
for(int i=0;s[i]!='\0';i++){
if(s[i]<='9'&&s[i]>='0')t*=10,t+=s[i]-'0';
else return -1;
}if(t>=1&&t<=1000)return t;
else return -1;
}
int main(){
cin >> a;
getchar();
getline(cin, b);
//cin>>a>>b;
//cout<<a<<' '<<b<<endl;
x=chang(a),y=chang(b);
if(x>0&&y>0) printf("%d + %d = %d",x,y,x+y);
else if(x>0) printf("%d + ? = ?",x);
else if(y>0) printf("? + %d = ?",y);
else printf("? + ? = ?");
return 0;
}
7-3 出租(20)set + map
0需要进行特判 利用set去重得到数组arr[ ],需注意a.rbegin()反向迭代器与正向迭代器不可混用,erase元素时直接*rbegin()删除元素本身
#include<bits/stdc++.h>
using namespace std;
long long n,n1;
string x,y;
set<int>a;
map<int,int>m;
int main(){
cin>>x;
for(int i=0;i<11;i++)n=n*10+x[i]-'0';
n1=n;
if(n==0)a.insert(0);
while(n) a.insert(n%10),n/=10;
printf("int[] arr = new int[]{");
int len=a.size();
for(int i=len,j=0;i>=1;i--,j++){
int t=*a.rbegin();
printf("%d",t);
if(i!=1)printf(",");
a.erase(*a.rbegin());
m[t]=j;
}
printf("};\nint[] index = new int[]{");
for(int i=0;i<11;i++){
printf("%d",m[x[i]-'0']);
if(i!=10)printf(",");
else printf("};");
}
}
7-4 判断素数(10)
1不是素数需要特判
#include<bits/stdc++.h>
using namespace std;
int n;
long long x;
int f;
void prime(long long x){
long long y=sqrt(x);
for(int i=2;i<=y;i++){
if(x%i==0){
f=0;
return;
}
}
}
int main(){
scanf("%d",&n);
for(int i=1;i<=n;i++){
scanf("%lld",&x);
f=1;
prime(x);
if(x==1)printf("No\n");
else if(f)printf("Yes\n");
else printf("No\n");
}
return 0;
}
7-9 红色警报(25)DFS计算连通分支
dfs深度优先遍历判断有几个连通分支,增加f[ ]记录是否被攻占
#include<bits/stdc++.h>
#include<unordered_map>
using namespace std;
const int N = 550;
//const double INF = 1e18;
int n,m,k,x,y;
int sum,sumt;
int f[N];//被攻占
int vis[N];//被访问
vector<int>edge[N];
void dfs(int x){
for(auto i:edge[x]){
if(!f[i]&&!vis[i]){//未被攻占且未被访问
vis[i]=1;
dfs(i);
}
}
}
int main(){
scanf("%d%d",&n,&m);
for(int i=1;i<=m;i++){
scanf("%d%d",&x,&y);
edge[x].push_back(y);
edge[y].push_back(x);
}
for(int i=0;i<n;i++){
if(!vis[i]){
dfs(i);sum++;
//printf("i:%d sum:%d\n",i,sum);
}
}//printf("%d\n",sum);
scanf("%d",&k);
int cnt=n;
for(int i=1;i<=k;i++){
scanf("%d",&x);
f[x]=1;sumt=0;cnt--;
memset(vis,0,sizeof(vis));
for(int j=0;j<n;j++){
if(!vis[j]&&!f[j]){
dfs(j);sumt++;
//printf("j:%d sumt:%d\n",j,sumt);
}
}
if(sumt<=sum)printf("City %d is lost.\n",x);
else printf("Red Alert: City %d is lost!\n",x);
sum=sumt;
if(!cnt)printf("Game Over.");
}
return 0;
}
7-10 列车调度(25)queue思想 + set
认真读题,输入的已经是反向序列,直接入队即可
利用set实现自动排序
b.upper_bound(m)大于m的最小数
#include<bits/stdc++.h>
using namespace std;
int n,m;
set<int>b;
int main() {
scanf("%d", &n);
for (int i = 1; i <= n; i++){
scanf("%d", &m);
if (b.upper_bound(m) != b.end()) {
b.erase(b.upper_bound(m));
}b.insert(m);
}printf("%d", b.size());
return 0;
}
7-12 愿天下有情人都是失散多年的兄妹(25)DFS
DFS递归追溯上五代出现过的人,标记是否出现过,记录深度d
有两条线需向上追溯时不能直接return
#include<bits/stdc++.h>
using namespace std;
const int N = 1e6;
char a[N];
int node[N][2];
int n, id, sex, f, m;
bool flag;
int vis[N];
void solve(int x,int d) {
//printf("d:%d vis[%d]:%d f:%d m:%d\n",d, x, vis[x],node[x][0],node[x][1]);
if (vis[x])flag=0;
vis[x] = 1;
if (d == 5)return;
if (node[x][0] != -1) solve(node[x][0], d + 1);
if (node[x][1] != -1) solve(node[x][1], d + 1);
}
int main() {
memset(node, -1, sizeof(node));
scanf("%d", &n);
for (int i = 1; i <= n; i++) {
scanf("%d", &id);
scanf("%s%d%d", &a[id], &f, &m);
a[f] = 'M', a[m] = 'F';
node[id][0] = f, node[id][1] = m;
}
int k, x, y; scanf("%d", &k);
for (int i = 1; i <= k; i++) {
scanf("%d%d", &x, &y);
if (a[x] == a[y])printf("Never Mind\n");
else {
memset(vis, 0, sizeof(vis));
flag = 1;
solve(x, 1); solve(y, 1);
if (flag)printf("Yes\n");
else printf("No\n");
}
}
return 0;
}
7-13 是否完全二叉搜索树(30)二叉搜索树 + 完全二叉树层序遍历
根据题目要求建立一颗二叉搜索树(左大右小),后层序遍历判断是否是完全二叉树(出现一个空节点后的所有节点需为空)
#include<bits/stdc++.h>
using namespace std;
int n,a[100],x;
void add(int x,int id){
if(!a[id])a[id]=x;
else if(a[id]<x)add(x,id*2);
else add(x,id*2+1);
return;
}
int main() {
memset(a,0,sizeof(a));
scanf("%d", &n);
for (int i = 1; i <= n; i++){
scanf("%d", &x);
add(x,1);
}queue<int>q;
q.push(1);
int f=1,ani=0;
while(!q.empty()){
int i=q.front(),t=a[i];q.pop();
if(a[i*2]){
if(ani)f=0;
q.push(i*2);
}else ani=1;
if(a[i*2+1]){
if(ani)f=0;
q.push(i*2+1);
}else ani=1;
printf("%d",t);
if(!q.empty())printf(" ");
}if(f)printf("\nYES");
else printf("\nNO");
return 0;
}
7-14 直捣黄龙(30)Dijkstra(路径+各种数组)+ unordered_map
单源无负边权->Dijsktra最短路
num[ ];//最短路条数
p[ ];//记录路径
sumv[ ];//打败敌军数量
numcity[ ];//救援城市数目
根据 最快速度(最短路径)->沿途解放最多城镇(numcity[ ])->有效杀伤最多敌军(sumv[ ])的次序判断并不断更新各个数组
unordered_map映射string->int及int->string
//最快速度->沿途解放最多城镇->有效杀伤最多敌军
#include<bits/stdc++.h>
#include<unordered_map>
using namespace std;
const int N = 205;
const double INF = 1e18;
int n,m,z,v[N],dist[N*4];//v[]敌军数
struct node{
int y,v;
node(int _y,int _v){y=_y,v=_v;}
};
vector<node>edge[N];
set<pair<int,int>>q;
unordered_map<string,int>mp;//字符对应序号
unordered_map<int,string>mp2;//序号到字符串
int num[N];//最短路条数
int p[N];//记录路径
int sumv[N];//打败敌军数量
int numcity[N];//救援城市数目
void Dijsktra(int s,int t){
memset(dist,127,sizeof(dist));
dist[s]=0;q.clear();num[s]=1;
for(int i=1;i<=n;i++)
q.insert(make_pair(dist[i],i));
while(!q.empty()){
int x=q.begin()->second;
q.erase(q.begin());
if(dist[x]>1<<30||x==t)break;
for(auto i:edge[x]){
if(dist[i.y]>dist[x]+i.v){
q.erase(make_pair(dist[i.y],i.y));
dist[i.y]=dist[x]+i.v;
q.insert(make_pair(dist[i.y],i.y));
numcity[i.y]=numcity[x]+1;
sumv[i.y]=sumv[x]+v[i.y];
p[i.y]=x;
num[i.y]=num[x];
}else if(dist[i.y]==dist[x]+i.v){
//if(dist[t]==mins)num++;
//else num=1,mins=dist[t];
num[i.y]+=num[x];
if(numcity[i.y]<numcity[x]+1){
numcity[i.y]=numcity[x]+1;
sumv[i.y]=sumv[x]+v[i.y];
p[i.y]=x;
}
else if(numcity[i.y]==numcity[x]+1){
if(sumv[i.y]<sumv[x]+v[i.y]){
sumv[i.y]=sumv[x]+v[i.y];
p[i.y]=x;
}
}
}
}
}
}
void findp(int x){
if(x!=1)findp(p[x]);
cout<<mp2[x]<<"->";
}
int main(){
scanf("%d%d",&n,&m);
string ss1,ss2,x,y;
cin>>x>>y;
mp[x]=1;mp2[1]=x;
for(int i=2;i<=n;i++){
cin>>ss1>>v[i];
mp[ss1]=i;mp2[i]=ss1;
}for(int i=1;i<=m;i++){
cin>>ss1>>ss2>>z;
edge[mp[ss1]].push_back(node(mp[ss2],z));
edge[mp[ss2]].push_back(node(mp[ss1],z));
}Dijsktra(mp[x],mp[y]);
findp(p[mp[y]]);
cout<<y<<endl;
printf("%d %d %d",num[mp[y]],dist[mp[y]],sumv[mp[y]]);
return 0;
}
7-14 直捣黄龙 (30 分)(djkstra,map,dfs)_forget……的博客-CSDN博客
7-15 水果忍者(30)几何
枚举每一条线段的下端点,从这个下端点向别的线段的上端点和下端点连线,然后判断一下(所有线段的上端点的最小斜率) 是不是大于 (所有线段的下端点的最小斜率),如果有合法的,那么所有线段的上端点的最小斜率对应的那个点和所有线段的下端点的最小斜率对应的点都是合法的,输出此时作为标准的点的下端点,另外一个点从两个合法的情况中找一个就可以了。
ps:假设当前枚举的是第i条线段,当我们枚举第i-1条线段的时候,形成的斜率可能会出现负数的情况。这个时候就相当于原来的上面的斜率变成了下面的斜率,下面的斜率变成了上面的斜率,注意坐标也要做相应的变化。
#include<bits/stdc++.h>
using namespace std;
# define ll long long
# define inf 0x3f3f3f3f
const int maxn = 2e4 + 100;
struct node {
int x, y1,y2;
}q[maxn];
int main() {
int n;
scanf("%d", &n);
for (int i = 1; i <= n; i++) {
scanf("%d%d%d", &q[i].x, &q[i].y1, &q[i].y2);
}
for (int i = 1; i <= n; i++) {
double minn = inf, maxx = -inf;
int xup, yup;
//xup=yup=0;
int j;
for (j = 1; j <= n; j++) {
if (j == i)continue;
int flag = 1;
double up = (q[j].y1 * 1.0 - q[i].y2 * 1.0) / (q[j].x * 1.0 - q[i].x * 1.0);
double down = (q[j].y2 * 1.0 - q[i].y2 * 1.0) / (q[j].x * 1.0 - q[i].x * 1.0);
if (up < down)swap(up, down), flag = 0;
if (down > minn || up < maxx)break;
//所有线段的上端点的最小斜率对应的那个点和所有线段的下端点的最小斜率对应的点都是合法的
//输出此时作为标准的点的下端点,另外一个点从两个合法的情况中找一个,此处取上端点
maxx = max(maxx, down);
if (minn > up) {
minn = up;
xup = q[j].x;
yup = q[j].y1;
if (!flag) yup = q[j].y2;
}
}
if (j == n + 1) {
printf("%d %d %d %d\n", q[i].x, q[i].y2, xup, yup);
break;
}
}
return 0;
}