7-12 愿天下有情人都是失散多年的兄妹
思路
核心思路:看双方在祖上五辈有没有重复的祖宗,如果有就No。这可以用DFS来实现。
具体:先dfs搜一遍男方上面五辈的祖先,标记一下。(如果发现祖上有不可考的,直接No)。接着dfs搜一遍女方上面的祖先,如果发现男方已经标记过了,就No;
需要注意的:父母亲和性别的数组初始化为-1,查询每对男女时都要初始化vis数组
DFS部分code
void dfs(int x,int level,int f) //x:人物,level:第几辈,f:男方or女方
{
if(level>5) return;
if(f==1 && !vis[x]) //男方且这个祖先没标记过
{
vis[x]=1; //标记
}
if(f==0 && vis[x]) /女方且这个祖先标记过了
{
flag=false;
return;
}
if(fa[x]!=-1&&flag) //父亲可考,搜父亲
{
dfs(fa[x],level+1,f);
}
if(ma[x]!=-1&&flag) //母亲可考,搜母亲
{
dfs(ma[x],level+1,f);
}
}
完整代码
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef pair<int,int> PII;
#define int ll
const int dx[8]={-1, 0, 1, 0, 1, -1, 1, -1};
const int dy[8]={0, 1, 0, -1, -1, 1, 1, -1};
#define N 100005
int vis[N],ma[N],fa[N],n,m,sex[N];
bool flag=true;
void dfs(int x,int level,int f)
{
if(level>5) return;
if(f==1 && !vis[x])
{
vis[x]=1;
}
if(f==0 && vis[x])
{
flag=false;
return;
}
if(fa[x]!=-1&&flag)
{
dfs(fa[x],level+1,f);
}
if(ma[x]!=-1&&flag)
{
dfs(ma[x],level+1,f);
}
}
void solve()
{
cin>>n;
memset(fa,-1,sizeof(fa));
memset(ma,-1,sizeof(ma));
memset(sex,-1,sizeof(sex));
while(n--)
{
int num;
char s;
cin>>num>>s;
if(s=='M') sex[num]=1;
else sex[num]=0;
cin>>fa[num];
cin>>ma[num];
if(fa[num]!=-1) sex[fa[num]]=1;
if(ma[num]!=-1) sex[ma[num]]=0;
}
cin>>m;
while(m--)
{
int a,b;
cin>>a>>b;
if(sex[a]==sex[b])
{
cout<<"Never Mind"<<endl;
continue;
}
flag = true;
memset(vis,0,sizeof(vis));
dfs(a,1,1);
dfs(b,1,0);
if(flag)
{
cout<<"Yes";
}else
{
cout<<"No";
}
if(m) cout<<endl;
}
}
signed main()
{
ios::sync_with_stdio(0);
cin.tie(0);
int T = 1;
//cin >> T;
while(T--) solve();
}
7-40 冰岛人
思路
这题看起来和上一题很像,但是只有父亲。不用dfs,直接往上遍历就可以。
这题可以使用map存储,map的key存储人民,map的first value存储性别,map的second value存储父亲。
其他情况就是简单的条件判断。
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef pair<int,int> PII;
#define int ll
const int dx[8]={-1, 0, 1, 0, 1, -1, 1, -1};
const int dy[8]={0, 1, 0, -1, -1, 1, 1, -1};
const int N=10010;
const double INF=1e9;
map<string,pair<int,string>>mp;
string fi,la,man,woman,tmp;
int n,m;
string check(string x,string y) //追溯祖先
{
int l1=0,l2=0;
while(x!="")
{
l2=0;
string z=y;
while(z!="")
{
if(x==z&&(l1<4||l2<4)) //有相同的祖先且在五辈内
{
return "No\n";
}
if(l1>=4&&l2>=4)
{
return "Yes\n";
}
z=mp[z].second;
l2++;
}
x=mp[x].second;
l1++;
}
return "Yes\n";
}
void solve()
{
cin>>n;
while(n--)
{
cin>>fi>>la;
if(la.back()=='n')
{
mp[fi].first=1;
mp[fi].second=la.substr(0,la.size()-4);
}
else if(la.back()=='r')
{
mp[fi].first=0;
mp[fi].second=la.substr(0,la.size()-7);
}
else if(la.back()=='m')
{
mp[fi].first=1;
}
else mp[fi].first=0;
}
cin>>m;
while(m--)
{
cin>>man>>tmp>>woman>>tmp;
if(!mp.count(man)||!mp.count(woman))
{
cout<<"NA"<<endl;
continue;
}
else if(mp[man].first==mp[woman].first)
{
cout<<"Whatever"<<endl;
continue;
}
else cout<<check(man,woman);
}
return;
}
signed main()
{
ios::sync_with_stdio(0);
cin.tie(0);
int T = 1;
//cin >> T;
while(T--) solve();
}
7-15 水果忍者
思路
如图所示
代码
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef pair<int,int> PII;
#define int ll
const int dx[8]={-1, 0, 1, 0, 1, -1, 1, -1};
const int dy[8]={0, 1, 0, -1, -1, 1, 1, -1};
const int N=10010;
const int INF=1e9;
double ansa,ansb,ansx,ansy,mink,maxk,ansmink,ansmaxk;
struct edge
{
double x;
double y1;
double y2;
}e[N];
bool cmp(edge a,edge b)
{
return a.x<b.x;
}
void solve()
{
int n;
cin>>n;
for(int i=0;i<n;i++)
{
cin>>e[i].x>>e[i].y1>>e[i].y2;
}
sort(e,e+n,cmp);
for(int i=0;i<n;i++)
{
ansmink=-INF;
ansmaxk=INF;
int j;
for(j=0;j<n;j++)
{
if(i==j) continue;
if(i<j)
{
mink=(e[j].y2-e[i].y2)/(e[j].x-e[i].x);
maxk=(e[j].y1-e[i].y2)/(e[j].x-e[i].x);
}
else{
mink=(e[j].y1-e[i].y2)/(e[j].x-e[i].x);
maxk=(e[j].y2-e[i].y2)/(e[j].x-e[i].x);
}
if(mink>ansmaxk||maxk<ansmink) break; //情况三
if(ansmaxk>maxk) //情况二
{
ansmaxk=maxk;
ansx=e[j].x;
ansy=e[j].y1;
}
ansmink=max(ansmink,mink); //情况二
}
if(j==n)
{
cout<<e[i].x<<" "<<e[i].y2<<" "<<ansx<<" "<<ansy;
return ;
}
}
return ;
}
signed main()
{
ios::sync_with_stdio(0);
cin.tie(0);
int T = 1;
//cin >> T;
while(T--) solve();
}
7-13 是否完全二叉搜索树
思路
如果是完全二叉树:最大的节点就等于节点个数
存储树:使用数组,如果空就插入,如果大于当前节点就往左插入,如果小于当前节点就往右插入
打印树:跳过空节点
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef pair<int,int> PII;
#define int ll
const int dx[8]={-1, 0, 1, 0, 1, -1, 1, -1};
const int dy[8]={0, 1, 0, -1, -1, 1, 1, -1};
const int N=1e5+10;
int n,x,tree[N],maxn;
void insert(int node) //插在a位置
{
maxn=max(maxn,node);
if(tree[node]==0)
tree[node]=x;
else
{
if(x>tree[node])
insert(node*2);
else
insert(node*2+1);
}
}
void print()///输出,从i到maxn 就是层序遍历,当值不为0时,表明存在节点
{
cout<<tree[1];
for(int i=2;i<=maxn;i++)
if(tree[i]!=0)
cout<<' '<<tree[i];
if(maxn==n)///比较最深节点与 n ,等于n才是完全二叉树
cout<<'\n'<<"YES";
else
cout<<'\n'<<"NO";
}
void solve()
{
cin>>n;
for(int i=0;i<n;i++)
{
cin>>x;
insert(1);
}
print();
}
signed main()
{
ios::sync_with_stdio(0);
cin.tie(0);
int T = 1;
//cin >> T;
while(T--) solve();
}