(PTA自主训练4)7-15 球队“食物链”

思路:记录每个点可以到哪些点,简单dfs,存一下遍历顺序,求最小的;


注意:注意剪枝,以及遍历顺序我是用vector来存的,当(未走过的点)不能够走向起点时,剪枝;

代码:

#include<bits/stdc++.h>
using namespace std;
vector< int >q[25];
int vis[25];
int dis[25][25];
vector< int >ans;
int n;
void dfs(int t,vector<int>&path){
    if(ans<path)return;
    if(path.size()==n){
        if(dis[path[n-1]][path[0]]==1){
            ans=min(ans,path);
        }
        return;
    }
    vis[t] = 1;
    int st=0;
    for (int i = 1; i <=n ; ++i) {
        if(!vis[i]&&dis[i][path[0]])
            st=1;
    }
    if(!st)return;
    for (int i = 0; i < q[t].size(); ++i) {
        auto g = q[t][i];
        if (!vis[g]) {
            path.push_back(g);
            vis[g]=1;
            dfs(g, path);
            vis[g]=0;
            path.pop_back();
        }
    }
}
int main(){
    cin>>n;
    for (int i = 0; i <n ; ++i) {
        ans.push_back(29);
    }
    for(int i=1;i<=n;i++){
        string s;
        cin>>s;
        for(int j=0;j<s.size();j++){
            if(s[j]=='W'){
                q[i].push_back(j+1);
                dis[i][j+1]=1;
            }
            else if(s[j]=='L'){
                q[j+1].push_back(i);
                dis[j+1][i]=1;
            }
        }
    }
    for(int i=1;i<=n;i++){
        vector< int >v;
        v.push_back(i);
        ::memset(vis,0,sizeof vis);
        vis[i]=1;
        dfs(i,v);
    }
    if(ans[0]==29){
        cout<<"No Solution";
        return 0;
    }
    for (int i = 0; i <n ; ++i) {
        cout<<ans[i];
        if(i!=n-1)
            cout<<' ';
    }
}

(PTA自主训练4)7-12 功夫传人

思路: 又是一道搜索题,赛时bfs拿了24分,赛后发现dfs就过了,很奇怪为啥,精度可能有问题

代码1BFS:

#include<bits/stdc++.h>
using namespace std;
vector< int >q[100005];
double  ans[100005];
int vis[100005];
int n;
int b[100005];
double z,r;
int main(){
    cin>>n>>z>>r;
    for(int i=0;i<n;i++){
        int k;
        cin>>k;
        if(k){
            while(k--){
                int x;
                cin>>x;
                q[i].push_back(x);
            }
        }
        else{
            int x;
            cin>>x;
            b[i]=x;
            vis[i]=1;
        }
    }
    queue< int >qe;
    qe.push(0);
    ans[0]=z;
    while (!qe.empty()){
        auto t=qe.front();
        qe.pop();
        for (auto i:q[t]) {
            if (vis[i]) {
                ans[i] = ans[t]*(1-r*1.0/100)*b[i];
            } else {
                ans[i] = ans[t]*(1-r*1.0/100);
                qe.push(i);
            }
        }
    }
    double   res=0;
    for (int i = 0; i <n ; ++i) {
        if(vis[i])res+=ans[i];
    }
    cout<<(int )res;
}

代码2:DFS

#include<bits/stdc++.h>
using namespace std;
vector< int >q[100005];
double  ans[100005];
int vis[100005];
int n;
double res;
int pd[100005];
int b[100005];
double z,r;
void dfs(int t,double pw){
    if(vis[t]){
        res+=pw*b[t];
        return;
    }
    for (int i = 0; i <q[t].size() ; ++i) {
        dfs(q[t][i],pw*(1-r/100));
    }
}
int main(){
    cin>>n>>z>>r;
    for(int i=0;i<n;i++){
        int k;
        cin>>k;
        if(k){
            while(k--){
                int x;
                cin>>x;
                q[i].push_back(x);
                pd[x]=1;
            }
        }
        else{
            int x;
            cin>>x;
            b[i]=x;
            vis[i]=1;
        }
    }
    dfs(0,z);
    cout<<(int )res;
}

(PTA自主训练3)7-10 列车调度

思路:讲真的,赛时没想到咋做,简单的交了一个很nc的代码,赛后补题发现规律性很强,思维题吧,(弱鸡思维跟不上),首先我们是保证得到一个降序的顺序,升序的那个加入ans,下一个数字从ans中找,找不到则加入,找的到则覆盖掉那个找到的位置的数。

考虑到查找以及有序性,提高时间效率则用到二分,因为set即有二分以及定点删除的作用,则使用set,upper_bond;

代码:

#include<bits/stdc++.h>
using namespace std;
int main(){
    int n;
    cin>>n;
    vector<int >q;
    for(int i=0;i<n;i++){
        int x;
        cin>>x;
        q.push_back(x);
    }
    vector< int >ans;
    ans.push_back(q[0]);
    for(int i=1;i<n;i++){
        int k=1;
        sort(ans.begin(),ans.end());
        for(int j=0;j<ans.size();j++){
            if(ans[j]>=num[i]){
                ans[j]=num[i];
                k=0;
                break;
            }
        }
        if(k){
            ans.push_back(num[i]);
        }
    }
    cout<<ans.size();
}

(PTA自主训练3)7-9 红色警报

思路:

主要是判断连通性:dfs查询连通性,删这个点之前的联通块的数量与删后的对比

代码:

#include<bits/stdc++.h>
using namespace std;
vector<int >ve[505];
int st[505];
int vis[505];
int del[505];
void dfs(int x){
    for (int i = 0; i <ve[x].size() ; ++i) {
        auto g=ve[x][i];
        if(vis[g]==0&&del[g]==0){
            vis[g]=1;
            dfs(g);
        }
    }
}
int main(){
    int n,m;
    cin>>n>>m;
    while(m--){
        int x,y;
        cin>>x>>y;
        ve[x].push_back(y);
        ve[y].push_back(x);
    }
    int ans=0;
    for (int i = 0; i <n ; ++i) {
        if(!vis[i]){
            vis[i]=1;
            ans++;
            dfs(i);
        }
    }
    int k;
    cin>>k;
    for(int i=0;i<k;i++) {
        int x;
        cin>>x;
        del[x]=1;
        ::memset(vis,0,sizeof vis);
        int ansing=0;
        for (int j = 0; j <n ; ++j) {
            if(vis[j]==0&&del[j]==0){
                vis[j]=1;
                ansing ++;
                dfs(j);
            }
        }
        if(ans<ansing){
            printf("Red Alert: City %d is lost!\n", x);
        }
        else{
            printf("City %d is lost.\n", x);
        }
        ans=ansing;
    }
    if(k==n) printf("Game Over.\n");
}

(PTA自主训练3)7-13 是否完全二叉搜索树

思路:根据树的性质,先建树,因为左子树大,右子树小,则可以还原树,然后bfs利用队列找出层序遍历,注意判断不存在的条件

条件:

  • 左边不存在,右节点存在
  • 根不存在,但左右节点存在
  • 左右节点若是有一个不存在,则标记一下

    代码:

    #include<bits/stdc++.h>
    using namespace  std;
    const int N=1e4+10;
    int l[N],r[N],t[N],idx;
    int vis[N],flag,st;
    void  build(int pos,int val){
    if(!vis[pos]){
        t[pos]=val;
        vis[pos]=1;
        return;
    }///如果这个节点没有被建立,先建立
    ///插入左子树
    if(val>t[pos]){
        if(l[pos]){
            build(l[pos],val);
        }
        else{
            l[pos]=++idx,build(l[pos],val);
        }
    }
    ////插入右子树
    else{
        if(r[pos]){
            build(r[pos],val);
        }
        else{
            r[pos]=++idx,build(r[pos],val);
        }
    }
    }
    void bfs(int x){
    queue<int >q;
    q.push(x);
    cout<<t[x];
    while(!q.empty()){
        int tt=q.front();
        if(tt!=x){
            cout<<' '<<t[tt];
        }
        q.pop();
        if(!l[tt]&&r[tt])flag=false;///左边不存在,右节点存在
        if(!st&&(l[tt]||r[tt]))flag=false;//////根不存在,但左右节点存在
        if(!l[tt]||!r[tt])st=false;////////左右节点若是有一个不存在,则标记一下
        if(l[tt])q.push(l[tt]);///压入层序遍历
        if(r[tt])q.push(r[tt]);
    }
    }
    int main(){
    int n;
    cin>>n;
    idx=1;
    for (int i = 1; i <=n ; ++i) {
        int g;
        cin>>g;
        build(1,g);
    }
    flag=st=1;
    bfs(1);
    puts("");
    if(flag)cout<<"YES";
    else
        cout<<"NO";
    }

    (PTA自主训练3)7-14 直捣黄龙

    思路:利用map映射字符串,建图,跑一遍堆优化的djstl,求最短路,然后用dfs从起点跑向终点,速度相同取ans.size()最大,其次再取cnt最大

    代码:

    #include<bits/stdc++.h>
    using namespace std;
    int n,k,s,e;
    string sta,ed;
    int val[205],dis[205],vis[205];
    vector<pair<int,int>>g[205];
    #define PII pair<int,int>
    unordered_map<string ,int >sti;
    unordered_map<int,string >its;
    vector<int >ans,now;
    int ansdis=-1,anscnt=-1,anstimes;
    void djstl(){
    fill(dis+1,dis+1+n,INT_MAX);
    dis[e]=0;
    priority_queue<PII,vector<PII>,greater<PII>>q;
    q.emplace(0,e);
    while (!q.empty()){
        auto [d,u]=q.top();
        q.pop();
        if(vis[u])continue;
        vis[u]=1;
        for(auto [v,w]:g[u]){
            if(vis[v])continue;
            if(dis[v]<=d+w)continue;
            dis[v]=d+w;
            q.emplace(dis[v],v);
        }
    }
    }
    void dfs(int x,int d,int cnt){
    if(d+dis[x]>ansdis)return;
    if(x==e&&d==ansdis){
        anstimes++;
        if(now.size()>ans.size()){
            anscnt=cnt,ans=now;
        }
        else if(now.size()==ans.size()&&cnt>anscnt){
            anscnt=cnt,ans=now;
        }
        return;
    }
    for(auto [v,w]:g[x]){
        if(vis[v])continue;
        now.push_back(v),vis[v]=1;
        dfs(v,d+w,cnt+val[v]);
        now.pop_back();vis[v]=0;
    }
    return;
    }
    int main(){
    cin>>n>>k>>sta>>ed;
    sti[sta]=1,its[1]=sta;
    for (int i = 2; i <=n ; ++i) {
        cin>>its[i]>>val[i],sti[its[i]]=i;
    }
    s=sti[sta],e=sti[ed];
    while(k--){
        int u,v,w;
        string us,vs;
        cin>>us>>vs>>w;
        u=sti[us],v=sti[vs];
        g[u].push_back({v,w});
        g[v].push_back({u,w});
    }
    djstl();
    fill(vis, vis + 1 + n, 0);
    ansdis=dis[s],vis[s]=1;
    dfs(s,0,0);
    cout<<sta;
    for (auto i:ans) {
        cout<<"->"<<its[i];
    }
    cout<<"\n"<<anstimes<<' '<<ansdis<<' '<<anscnt<<endl;
    return 0;
    }

    (PTA自主训练3)7-12 愿天下有情人都是失散多年的兄妹

    思路:本题主要是是判断俩人是否在五代以内,可以考虑用图来解决,将每个人的母亲与父亲存入图中,从本身跑dfs对父母进行搜索,将搜到的人标记,如果深度五层以内,搜到了曾经标记过的,则说明两人近亲,no

    代码:

    #include<bits/stdc++.h>
    using namespace std;
    int fa[100005],ma[100005],sex[100005],vis[100005],flag;
    void dfs(int a,int n){
    if(n==0)return ;
    if(vis[a]==1){
        flag=1;
        return;
    }
    vis[a]=1;
    if(fa[a]!=-1&&fa[a]!=0)dfs(fa[a],n-1);
    if(ma[a]!=-1&&ma[a]!=0)dfs(ma[a],n-1);
    }
    int main(){
    int n;
    cin>>n;
    for (int i = 0; i <n ; ++i) {
            int num;
            cin>>num;
            char c;
            cin>>c;
            if(c=='M'){
                sex[num]=0;
            }
            else
                sex[num]=1;
            int f,m;
            cin>>f>>m;
            fa[num]=f,ma[num]=m;
            sex[f]=0,sex[m]=1;
    }
    int k;
    cin>>k;
    for (int i = 0; i < k ; ++i) {
        int a,b;
        ::memset(vis,0,sizeof vis);
        cin>>a>>b;
        if(sex[a]==sex[b]){
            cout<<"Never Mind\n";
            continue;
        }
        flag=0;
        dfs(a,5);
        dfs(b,5);
        if(flag==0)
            cout<<"Yes\n";
        else
            cout<<"No\n";
    }
    }

(PTA训练赛8)L2-3 完全二叉树的层序遍历

思路:又节点的个数,找出后序遍历的序号,然后通过映射,输出其层序遍历的答案,比如:n=8,那么后序遍历则为:8 4 7 2 3 5 6 1,那么其层序遍历的答案则为a[8],a[4],a[7]------等

代码:

#include<bits/stdc++.h>
using namespace std;
int res[31];
int cnt=1;
int n;
int post[32];
void postorder(int t){
    if(t>n)
        return ;
    postorder(t*2);
    postorder(t*2+1);
    post[t]=cnt++;
}
int main(){
    cin>>n;
    vector<int>ans;
    vector<pair<int,int>>q;
    postorder(1);
    ans.push_back(0);
    for (int i = 1; i <=n ; ++i) {
        int x;
        cin>>x;
        ans.push_back(x);
    }
    for (int i = 1; i <=n ; ++i) {
        cout<<ans[post[i]]<<" \n"[i==n];
    }
}

#

posted on 2023-04-20 14:49  IR101  阅读(10)  评论(0编辑  收藏  举报  来源