天梯赛L3部分题解

L3-001 凑零钱

在这里插入图片描述

#include<bits/stdc++.h>
using namespace std;

const int N=1e4+4,M=104;

int f[M],v[N];
int pre[N][M];

int main(){
    int n,m;
    cin>>n>>m;
    for(int i=0;i<n;i++) cin>>v[i];
    sort(v,v+n,greater<int>());
    
    for(int i=0;i<n;i++){
        for(int j=m;j>=v[i];j--){
            if(f[j]<=f[j-v[i]]+v[i]){//最小序,要等于号
                f[j]=f[j-v[i]]+v[i];
                pre[i][j]=1;
            }
        }
    }
    if(f[m]!=m){
        cout<<"No Solution"<<endl;
        return 0;
    }
    int j=m,i=n-1,flag=0;
    while(i>=0&&j>=0){
        if(pre[i][j]){
            if(!flag) cout<<v[i],flag=1;
            else cout<<" "<<v[i];
            j-=v[i];
        }
        i--;
    }
    return 0;
}

L3-002 特殊堆栈

在这里插入图片描述

#include<bits/stdc++.h>
using namespace std;
const int N=1e5+10;
vector<int> v;//v(N),push_back操作后v[N]==v,相当于v[0]~v[N-1]初始化为0了
stack<int> sk;

int main(){
    int n,x;
    string s;
    cin>>n;
    while(n--){
        cin>>s;
        if(s[1]=='u'){
            cin>>x;
            sk.push(x);
            if(v.size()==0){
                v.push_back(x);
                continue;
            }
            auto it=lower_bound(v.begin(),v.end(),x);
            v.insert(it,x);
        }else if(s[1]=='o'){
            if(sk.size()==0){
                cout<<"Invalid"<<endl;
                continue;
            }
            int t=sk.top();
            sk.pop();
            cout<<t<<endl;
            auto it=lower_bound(v.begin(),v.end(),t);
            v.erase(it);
        }else{
            if(sk.size()==0){
                cout<<"Invalid"<<endl;
                continue;
            }
            int it;
            if(sk.size()&1){
                it=(sk.size()+1)/2-1;
            }else{
                it=(sk.size()/2)-1;
            }
            cout<<v[it]<<endl;
        }
    }
    return 0;
}

L3-003 社交集群

在这里插入图片描述

#include<bits/stdc++.h>
using namespace std;

const int N=1010;
int p[N],root[N],x,n,k,st[N];
vector<int> ans;
void init(){
    for(int i=0;i<N;i++) p[i]=i;
}
int find(int x){
    if(p[x]!=x) p[x]=find(p[x]);
    return p[x];
}
void merge(int a,int b){
    int pa=find(a),pb=find(b);
    if(pa!=pb){
        p[pa]=pb;
    }
}

int main(){
    char ch[2];
    cin>>n;
    init();
    for(int i=1;i<=n;i++){
        cin>>k>>ch;
        for(int j=0;j<k;j++){
            cin>>x;
            if(root[x]==0) root[x]=i;
            merge(i,root[x]);
        }
    }
    for(int i=1;i<=n;i++){
        st[find(i)]++;
    }
    for(int i=1;i<=n;i++){
        if(st[i]){
            ans.push_back(st[i]);
        }
    }
    sort(ans.begin(),ans.end(),greater<int>());
    cout<<ans.size()<<endl;
    for(int i=0;i<ans.size();i++){
        if(i) cout<<" "<<ans[i];
        else cout<<ans[i];
    }
    return 0;
}

L3-004 肿瘤诊断

在这里插入图片描述

#include<bits/stdc++.h>
using namespace std;
int a[65][1290][135];
int m,n,l,t1,sum=0;
struct node{
    int z,x,y;
};
int dx[]={0,-1,0,1,0,0},dy[]={-1,0,1,0,0,0},dz[]={0,0,0,0,-1,1};

void bfs(int sz,int sx,int sy){
    int cnt=1;//要进去的时候标记然后++,不能弹出的时候,不然同一个点可能会被多次弹出,使得cnt错误
    queue<node> q;
    q.push({sz,sx,sy});
    // auto t2=q.front();
    // cout<<t2.z<<" "<<t2.x<<" "<<t2.y<<endl;
    a[sz][sx][sy]=0;
    while(q.size()){
        auto t=q.front();
        q.pop();
        for(int i=0;i<6;i++){
            int z=t.z+dz[i],x=t.x+dx[i],y=t.y+dy[i];//有段错误,指针数组越界,记得检查下标。y=t.y+dy[y]debug半天
            if(z>0&&z<=l&&x>0&&x<=m&&y>0&&y<=n&&a[z][x][y]){
                q.push({z,x,y});
                a[z][x][y]=0;
                cnt++;
            }
        }
    }
    // cout<<cnt<<endl;
    if(cnt>=t1) sum+=cnt;
}
int main(){
    cin>>m>>n>>l>>t1;
    for(int i=1;i<=l;i++){
        for(int j=1;j<=m;j++){
            for(int k=1;k<=n;k++){
                cin>>a[i][j][k];
            }
        }
    }
    for(int i=1;i<=l;i++){
        for(int j=1;j<=m;j++){
            for(int k=1;k<=n;k++){
                if(a[i][j][k]){
                    bfs(i,j,k);
                }
            }
        }
    }
    cout<<sum<<endl;
    return 0;
}

L3-005 垃圾箱分布

在这里插入图片描述

#include<bits/stdc++.h>
using namespace std;
const int N=1050,inf=0x3f3f3f3f;
int n,m,k,ds;
int g[N][N],d[N];
bool st[N];
double ansavg=inf,anslen=-1;//初始化要注意,求avg最小则初始化很大,求最短距离最长就初始化很小
int ansid=-1;

void dj(int s){
    memset(d,0x3f,sizeof d);
    d[s]=0;
    memset(st,false,sizeof st);
    for(int i=1;i<=n+m;i++){
        int t=-1;
        for(int j=1;j<=n+m;j++){
            if(!st[j]&&(t==-1||d[t]>d[j]))
                t=j;
        }
        st[t]=true;
        for(int j=1;j<=n+m;j++){
            if(d[j]>d[t]+g[t][j]){
                d[j]=d[t]+g[t][j];
            }
        }
    }
}

int main(){
    cin>>n>>m>>k>>ds;
    memset(g,0x3f,sizeof g);
    //fill(g[0],g[0]+N*N,0x3f3f3f3f);
    memset(d,0x3f,sizeof d);
    for(int i=0;i<N;i++) g[i][i]=0;
    
    while(k--){
        string a,b;
        int l,t1,t2;
        cin>>a>>b>>l;
        if(a[0]=='G') a=a.substr(1),t1=stoi(a)+n;
        else t1=stoi(a);
        if(b[0]=='G') b=b.substr(1),t2=stoi(b)+n;
        else t2=stoi(b);
        g[t1][t2]=g[t2][t1]=l;
    }
    for(int ide=n+1;ide<=n+m;ide++){
        dj(ide);
        double avg=0;
        double len=0x3f3f3f3f;//求最短距离所以初始化很大
        for(int i=1;i<=n;i++){
            if(d[i]>ds){
                len=-1;
                break;
            }
            if(d[i]<len) len=d[i];
            avg+=1.0*d[i];
        }
        avg=avg/n;
        if(len==-1) continue;
        if(anslen<len){
            anslen=len;
            ansavg=avg;
            ansid=ide-n;
        }else if(anslen==len&&avg<ansavg){
            anslen=len;
            ansavg=avg;
            ansid=ide-n;
        }
    }
    if(ansid==-1){
        cout<<"No Solution";
    }else{
        cout<<"G"<<ansid<<endl;
        // cout<<ansavg<<endl;
        printf("%.1lf %.1lf",anslen,ansavg);
    }
    return 0;
}

L3-007 天梯地图

在这里插入图片描述
在这里插入图片描述

#include<bits/stdc++.h>
using namespace std;
const int N=505,inf=0x3f3f3f3f;
int g[N][N],g1[N][N];//距离,时间
int d[N],d1[N];//距离,时间
int dis[N],num[N];
int n,m;
int sta,ed;
bool st[N],st1[N];
vector<int> v,v1;
int pre[N],pre1[N];

void serv(int pre[],vector<int> &v){
    int t=ed;
    while(t!=sta){
        v.push_back(t);
        t=pre[t];
    }
    v.push_back(sta);
}

void dj(){//距离
    memset(d,0x3f,sizeof d);
    memset(num,0x3f,sizeof num);
    d[sta]=0;
    num[sta]=1;
    for(int i=0;i<n;i++){
        int t=-1;
        for(int j=0;j<n;j++){
            if(!st[j]&&(t==-1||d[j]<d[t]))
                t=j;
        }
        st[t]=true;
        for(int j=0;j<n;j++){
            // if(d[j]>d[t]+g[t][j]){
            //     d[j]=d[t]+g[t][j];
            //     num[j]=num[t]+1;
            //     pre[j]=t;
            // }else if(d[j]==d[t]+g[t][j]&&num[j]>num[t]+1){//不能num[j]<num[t]+1判断,因为num初始都是0。
                // d[j]=d[t]+g[t][j];
                // num[j]=num[t]+1;
                // pre[j]=t;
            // }
            if(d[j]>d[t]+g[t][j]||(d[j]==d[t]+g[t][j]&&num[j]>num[t]+1)){
                d[j]=d[t]+g[t][j];
                num[j]=num[t]+1;
                pre[j]=t;
            }
        }
    }
    serv(pre,v);
}

void dj1(){//时间
    memset(d1,0x3f,sizeof d1);
    d1[sta]=0;
    for(int i=0;i<n;i++){
        int t=-1;
        for(int j=0;j<n;j++){
            if(!st1[j]&&(t==-1||d1[j]<d1[t]))
                t=j;
        }
        st1[t]=true;
        for(int j=0;j<n;j++){
            if(d1[j]>d1[t]+g1[t][j]){
                d1[j]=d1[t]+g1[t][j];
                dis[j]=dis[t]+g[t][j]; 
                pre1[j]=t;
            }else if(d1[j]==d1[t]+g1[t][j]&&dis[j]>dis[t]+g[t][j]){
                d1[j]=d1[t]+g1[t][j];
                dis[j]=dis[t]+g[t][j]; 
                pre1[j]=t;
            }
        }
    }
    serv(pre1,v1);
}
int main(){
    cin>>n>>m;
    memset(g,0x3f,sizeof g);
    memset(g1,0x3f,sizeof g1);
    while(m--){
        int a,b,c,d,e;
        cin>>a>>b>>c>>d>>e;
        if(c==1){
            g[a][b]=d;
            g1[a][b]=e;
        }else{
            g[a][b]=g[b][a]=d;
            g1[a][b]=g1[b][a]=e;
        }
    }
    cin>>sta>>ed;
    dj(),dj1();
    if(v==v1){
        printf("Time = %d; Distance = %d: %d",d1[ed],d[ed],v1[v1.size()-1]);
        for(int i=v1.size()-2;i>=0;i--){
            cout<<" => "<<v1[i];
        }
    }else{
        printf("Time = %d: %d",d1[ed],v1[v1.size()-1]);
        for(int i=v1.size()-2;i>=0;i--){
            cout<<" => "<<v1[i];
        }
        cout<<endl;
        printf("Distance = %d: %d",d[ed],v[v.size()-1]);
        for(int i=v.size()-2;i>=0;i--){
            cout<<" => "<<v[i];
        }
    }
    return 0;
}

L3-008 喊山

在这里插入图片描述
在这里插入图片描述

#include<bits/stdc++.h>
using namespace std;
const int N=10010;
typedef pair<int,int> pii;
int n,m,k;
vector<int> v[N];//小括号是一维初始化,中括号是二维数组 
bool st[N];

int bfs(int x){
    memset(st,false,sizeof st);
    int ansid=10010,ansh=0;
    queue<pii> q;
    q.push({x,1});
    st[x]=true;//进去就标记不要忘记了
    while(q.size()){
        auto t=q.front();
        q.pop();
        int var=t.first,hg=t.second;
        // cout<<var<<" "<<hg<<endl;
        if(ansh<hg){
            ansh=hg;
            ansid=var;
        }else if(ansh==hg){
            ansid=min(ansid,var);
        }
        for(auto i:v[var]){
            if(!st[i]){
                q.push({i,hg+1});
                st[i]=true;
            }
        }
        
    }
    // cout<<"hh"<<endl;
    return ansid;
}
int main(){
    cin>>n>>m>>k;
    while(m--){
        int a,b;
		cin>>a>>b;
        v[a].push_back(b);
		v[b].push_back(a);
    }
    while(k--){
        int x;cin>>x;
        if(v[x].size()==0) cout<<"0"<<endl;
        else cout<<bfs(x)<<endl;
    }
    return 0;
}

L3-009 长城

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

#include<bits/stdc++.h>
using namespace std;
const int N=1e5+10;
long long stk[N],tt,n,x[N],y[N];//记得开long long,两个数相乘
bool st[N];

bool check(int l,int mid,int r){
    return (y[r]-y[l])*(x[mid]-x[l])>=(y[mid]-y[l])*(x[r]-x[l]);
}
int main(){
    cin>>n;
    int ans=0;
    for(int i=0;i<n;i++){
        cin>>x[i]>>y[i];
        if(tt){
            while(tt>1&&check(i,stk[tt],stk[tt-1])){
                tt--;
            }
            if(tt!=1&&!st[stk[tt]]){
                ans++;
                st[stk[tt]]=true;
            }
        }
        stk[++tt]=i;
    }
    cout<<ans<<endl;
    return 0;
}

L3-010 是否完全二叉搜索树

在这里插入图片描述

#include<bits/stdc++.h>
using namespace std;
const int N=1<<20;
int n,t,tree[N];

void build(int x){
    if(tree[x]==0)
        tree[x]=t;
    else if(tree[x]<t){
        build(x<<1);
    }else{
        build(x<<1|1);
    }
}

int main(){
    cin>>n;
    for(int i=0;i<n;i++){
        cin>>t;
        build(1);
    }
    bool flag=false;
    for(int cnt=1,k=1;cnt<=n;k++){
        if(tree[k]==0){
            flag=true;
        }else{
            cout<<tree[k];
            cout<<(cnt++!=n?" ":"");
        }
    }
    cout<<endl;
    if(flag) cout<<"NO"<<endl;
    else cout<<"YES"<<endl;
    return 0;
}

L3-011 直捣黄龙

在这里插入图片描述
在这里插入图片描述

#include<bits/stdc++.h>
using namespace std;
const int N=501,inf=0x3f3f3f3f;
int g[N][N];
string sta,ed;
int edd;
int d[N],num[N],sum[N],enemy[N],cnt[N];//距离,节点数,总敌人数,每个点敌人数,最短路径方案数
int pre[N];
bool st[N];
vector<string> v;
map<string,int> sti;
map<int,string> its;
int idx=1;
int n,k;
void serv(int pre[]){
    int p=edd;
    while(p!=0){
        v.push_back(its[p]);
        p=pre[p];
    }
    v.push_back(its[0]);
}
void dj(){
    memset(d,0x3f,sizeof d);
    d[0]=0;
    cnt[0]=1;
    for(int i=0;i<n;i++){
        int t=-1;
        for(int j=0;j<n;j++){
            if(!st[j]&&(t==-1||d[j]<d[t]))
                t=j;
        }
        st[t]=true;
        for(int j=0;j<n;j++){
            if(d[j]>d[t]+g[t][j]){
                d[j]=d[t]+g[t][j];
                num[j]=num[t]+1;
                sum[j]=sum[t]+enemy[j];
                cnt[j]=cnt[t];
                pre[j]=t;
            }else if(d[j]==d[t]+g[t][j]){
                cnt[j]+=cnt[t];//单纯的当d[j]==d[t]+g[t][j]相等的时候路径数量就得加
//if(d[j]==d[t]+g[t][j]&&num[j]<num[t]+1)
//或者if(d[j]==d[t]+g[t][j]&&num[j]==num[t]+1&&sum[t]<sum[t]+enemy[j])的时候加cnt[j]+=cnt[t]不行
//cnt是单纯的路径长度相等加,例如当路径长度,节点数,总敌人数都一样的时候也得更新路径条数。
                if(num[j]<num[t]+1){//尽量多的点就<
                    num[j]=num[t]+1;
                    sum[j]=sum[t]+enemy[j];
                    pre[j]=t;
                }else if(num[j]==num[t]+1&&sum[j]<sum[t]+enemy[j]){
                    sum[j]=sum[t]+enemy[j];
                    pre[j]=t;
                }
            }
            
        }

    }
    serv(pre);
}
int main(){
    memset(g,0x3f,sizeof g);
    // for(int i=0;i<N;i++) g[i][i]=0;
    cin>>n>>k>>sta>>ed;
    string a,b;
    int x,le;
    for(int i=0;i<n-1;i++){
        cin>>a>>x;
        sti[a]=idx;
        its[idx]=a;
        enemy[sti[a]]=x;
        idx++;
    }
    // n=idx;
    // cout<<n<<endl;
    sti[sta]=0,its[0]=sta,edd=sti[ed];
    while(k--){
        cin>>a>>b>>le;
        g[sti[a]][sti[b]]=g[sti[b]][sti[a]]=le;
    }
    dj();
    for(int i=v.size()-1;i>=0;i--){
        cout<<(i==v.size()-1?"":"->")<<v[i];
    }
    cout<<endl<<cnt[edd]<<" "<<d[edd]<<" "<<sum[edd]<<endl;
    return 0;
}

L3-012 水果忍者

在这里插入图片描述
在这里插入图片描述

#include<bits/stdc++.h>
using namespace std;
const int N=1e4+10,inf=0x3f3f3f3f;
double mxk,mnk,tmxk,tmnk;
struct node{
    double x,y1,y2;//要用double类型,不然会损失精度
    bool operator<(const node& w) const{
        return x<w.x;
    }
}f[N];
int n,ansx,ansy;

int main(){
    cin>>n;
    for(int i=0;i<n;i++){
        cin>>f[i].x>>f[i].y1>>f[i].y2;
    }
    sort(f,f+n);
    for(int i=0,j;i<n;i++){
        mxk=inf,mnk=-inf;//根据j内的进行收缩
        for(j=0;j<n;j++){
            if(i==j) continue;
            if(i<j){
                tmxk=(f[j].y1-f[i].y2)/(f[j].x-f[i].x);
                tmnk=(f[j].y2-f[i].y2)/(f[j].x-f[i].x);
            }else{
                tmxk=(f[i].y2-f[j].y2)/(f[i].x-f[j].x);
                tmnk=(f[i].y2-f[j].y1)/(f[i].x-f[j].x);
            }
            if(tmnk>mxk||mnk>tmxk) break;
            if(tmxk<mxk){
                mxk=tmxk;
                ansx=f[j].x;
                ansy=f[j].y1;
            }
            mnk=max(mnk,tmnk);
        }
        if(j==n){
            //以i为基点的下面那个点,j找上面那个点,y1>y2
            cout<<ansx<<" "<<ansy<<" "<<(int)f[i].x<<" "<<(int)f[i].y2;
            break;
        }
    }
    return 0;
}

L3-013 非常弹的球

在这里插入图片描述
在这里插入图片描述

#include<bits/stdc++.h>
using namespace std;

int main(){
    double w,p,v2,s=0;
    cin>>w>>p;
    p=(100-p)/100;
    v2=2*1000*100/w;
    while(v2>1e-6){
        s+=v2/9.8;//动能转换为重力势能,h
        v2=v2*p;
    }
    printf("%.3lf",s);
    return 0;
}

L3-014 周游世界

在这里插入图片描述
在这里插入图片描述
DFS解法

#include<bits/stdc++.h>
using namespace std;
const int N=10005;
vector<vector<int> > v(N);
int line[N][N],st[N];
vector<int> path,tpath;

int transfer(vector<int> t){
    int cnt=-1,preline=0;
    for(int i=1;i<t.size();i++){
        if(line[t[i-1]][t[i]]!=preline){
            cnt++;
        }
        preline=line[t[i-1]][t[i]];
    }
    return cnt;
}

void dfs(int node,int ed,int cnt,int &mincnt,int &mintransfer){//注意带引用符
    if(node==ed&&(cnt<mincnt||(cnt==mincnt&&transfer(tpath)<mintransfer))){
        mincnt=cnt;
        mintransfer=transfer(tpath);
        path=tpath;
    }
    if(node==ed) return;
    for(int i=0;i<v[node].size();i++){
        if(!st[v[node][i]]){
            st[v[node][i]]=1;
            tpath.push_back(v[node][i]);
            dfs(v[node][i],ed,cnt+1,mincnt,mintransfer);
            st[v[node][i]]=0;
            tpath.pop_back();
        }
    }
}

int main(){
    int n,m,k,pre,temp,a,b;
    cin>>n;
    for(int i=1;i<=n;i++){
        cin>>m>>pre;
        for(int j=1;j<m;j++){
            cin>>temp;
            line[pre][temp]=line[temp][pre]=i;
            v[pre].push_back(temp);
            v[temp].push_back(pre);
            pre=temp;
        }
    }
    cin>>k;
    while(k--){
        int mincnt=99999,mintransfer=99999;
        cin>>a>>b;
        tpath.clear();
        tpath.push_back(a);
        st[a]=1;
        dfs(a,b,0,mincnt,mintransfer);
        st[a]=0;
        if(mincnt==99999){
            cout<<"Sorry, no line is available."<<endl;
            continue;
        }
        cout<<mincnt<<endl;
        int preline=0,pretransfer=a;
        for(int j=1;j<path.size();j++){
            if(line[path[j-1]][path[j]]!=preline){
                if(preline!=0) printf("Go by the line of company #%d from %04d to %04d.\n",preline,pretransfer,path[j-1]);
                preline=line[path[j-1]][path[j]];
                pretransfer=path[j-1];
            }
        }
        printf("Go by the line of company #%d from %04d to %04d.\n",preline,pretransfer,b);
    }
}

最短路解法

#include<bits/stdc++.h>
using namespace std;
const int N=10005,M=100*N;
typedef pair<int,int> pii;
int h[N],e[M],ne[M],com[M],step[M],idx;//company
int d[N],cnt[N],s[N],pre[N];//距离最短为第一排序条件,中转最少为第二条件
bool st[N];
string node[N];

void add(int a,int b,int len,int i){
    e[idx]=b,ne[idx]=h[a],step[idx]=len,com[idx]=i,h[a]=idx++;
}
string get_num(int t){
    string s=to_string(t);
    while(s.size()<4) s="0"+s;
    return s;
}
void dj(int src,int des){
    memset(d,0x3f,sizeof d);
    memset(cnt,0x3f,sizeof cnt);
    memset(st,false,sizeof st);
    d[src]=cnt[src]=0;
    priority_queue<pii,vector<pii>,greater<pii> > q;
    q.push({0,src});
    while(q.size()){
        auto t=q.top();q.pop();
        int dis=t.first,ver=t.second;
        if(st[ver]) continue;
        st[ver]=true;
        for(int i=h[ver];~i;i=ne[i]){
            int j=e[i];
            if(d[j]>d[ver]+step[i]){
                d[j]=d[ver]+step[i];
                if(com[ver]!=com[i]){
                    cnt[j]=cnt[ver]+1;
                }
                pre[j]=ver;
                //从点ver到点j的路径,com[i]不同的idx则不同。
                node[j]="Go by the line of company #"+to_string(com[i])+" from "+get_num(ver)+" to "+get_num(j)+".";
                q.push({d[j],j});
            }else if(d[j]==d[ver]+step[i]&&cnt[j]>cnt[ver]+1){
                cnt[j]=cnt[ver]+1;
                pre[j]=ver;
                node[j]="Go by the line of company #"+to_string(com[i])+" from "+get_num(ver)+" to "+get_num(j)+".";
            }
        }
    }
    if(d[des]==0x3f3f3f3f){
        cout<<"Sorry, no line is available."<<endl;
        return;
    }
    cout<<d[des]<<endl;
    vector<string> ans;
    int p=des;
    while(p!=src){
        ans.push_back(node[p]);
        p=pre[p];
    }
    // ans.push_back(node[p]);
    for(int i=ans.size()-1;i>=0;i--){
        cout<<ans[i]<<endl;
    }
    return;
}
int main(){
    memset(h,-1,sizeof h);
    int n,m,k;
    cin>>n;
    for(int i=1;i<=n;i++){
        cin>>m;
        for(int j=1;j<=m;j++) cin>>s[j];
        for(int j=1;j<=m;j++){
            for(int k=j+1;k<=m;k++){
                int dis=k-j;
                if(s[1]==s[k]) dis=min(dis,k-dis-1);//环形的,一共k个点,dis为两点之间的距离,k-dis-1为另一条路线的dis为两点之间的距离
                add(s[j],s[k],dis,i),add(s[k],s[j],dis,i);
            }
        }
    }
    cin>>k;
    while(k--){
        int a,b;cin>>a>>b;
        dj(a,b);
    }
    return 0;
}

L3-015 球队“食物链”

在这里插入图片描述
在这里插入图片描述

#include<bits/stdc++.h>
using namespace std;
const int N=25;
int v[N][N],n;
int ans[N];
bool flag,st[N];

void dfs(int index,int num){//ans[index]=num在第index位置放数num球队
    if(flag==1) return;
    ans[index]=num;
    if(index==n&&v[num][1]){
        flag=1;
        return;
    }
    if(index==n) return;
    bool cut=false;
    for(int i=1;i<=n;i++){
        if(!st[i]&&v[i][1]){
            cut=true;
            break;
        }
    }
    if(!cut) return;//剩下球队没有能打败球队1的队伍,直接退出,不满足条件
    
    st[num]=true;
    for(int i=1;i<=n;i++){
        if(!st[i]&&v[num][i]){
            dfs(index+1,i);
        }
    }
    st[num]=false;
}
int main(){
    cin>>n;
    char s[N];
    for(int i=1;i<=n;i++){
        scanf("%s",s+1);
        for(int j=1;j<=n;j++){
            if(s[j]=='W') v[i][j]=1;
            if(s[j]=='L') v[j][i]=1;
        }
    }
    dfs(1,1);
    if(flag){
        for(int i=1;i<=n;i++){
            cout<<(i==1?"":" ")<<ans[i];
        }
    }else{
        cout<<"No Solution";
    }
    return 0;
}

L3-016 二叉搜索树的结构

在这里插入图片描述
在这里插入图片描述

#include <bits/stdc++.h>
using namespace std;
struct node {
	int num, lchild, rchild, parent, level;
	node() {
		lchild = rchild = parent = -1;
	}
}Tree[128];
int n, m, a, b, in, cnt, root = 1, f;
map<int, int> Find;
string t;
void insert(int x) {
	int now = root;
	while(Tree[now].num != x) {
		if (x < Tree[now].num) {
			if (Tree[now].lchild == -1) {
				Tree[cnt].num = x;
				Tree[cnt].level = Tree[now].level + 1;
				Tree[cnt].parent = now;
				Tree[now].lchild = cnt;
			}
			now = Tree[now].lchild;
		} else {
			if (Tree[now].rchild == -1) {
				Tree[cnt].num = x;
				Tree[cnt].level = Tree[now].level + 1;
				Tree[cnt].parent = now;
				Tree[now].rchild = cnt;
			}
			now = Tree[now].rchild;
		}
	}
}
int main() {
	cin >> n >> in;
	Tree[++cnt].num = in;
	Find[in] = cnt;
	for (int i = 1; i < n; i++) {
		cin >> in;
		Find[in] = ++cnt;
		insert(in);
	}
	cin >> m;
	while (m--) {
		f = 0;
		cin >> a >> t;
		if (t == "is") {
			cin >> t >> t;
			if (t == "root") {
				if (Find[a] == root) f = 1;
			} else if (t == "parent") {
				cin >> t >> b;
				if (Tree[Find[b]].parent == Find[a]) f = 1;
			} else if (t == "left") {
				cin >> t >> t >> b;
				if (Tree[Find[b]].lchild == Find[a]) f = 1;
			} else {
				cin >> t >> t >> b;
				if (Tree[Find[b]].rchild == Find[a]) f = 1;
			}
		} else {
			cin >> b >> t >> t;
			if (t == "siblings") {
				if (Find[a] && Find[b] && Tree[Find[a]].parent == Tree[Find[b]].parent) f = 1;
			} else {
				cin >> t >> t >> t;
				if (Find[a] && Find[b] && Tree[Find[a]].level == Tree[Find[b]].level) f = 1;
			}
		}
		cout << (f ? "Yes" : "No") << '\n';
	}
	return 0;
}

L3-017 森森快递

在这里插入图片描述
在这里插入图片描述

#include<bits/stdc++.h>
using namespace std;
#define lc p<<1
#define rc p<<1|1
#define debug(x) cout<<#x<<" = "<<x<<endl
#define int long long
typedef long long ll;
const int N=1e5+10;
int n,q,x,w[N],ans;

struct node{
	int l,r,var,add;
}tr[4*N];
struct eg{
	int l,r;
	bool operator<(const eg&w) const{
		if(r!=w.r) return r<w.r;
		return l>w.l;
	}
}e[N];

void pushup(int p){
	tr[p].var=min(tr[lc].var,tr[rc].var);
}
void pushdown(int p){
	if(tr[p].add){
		tr[lc].var+=tr[p].add;
		tr[rc].var+=tr[p].add;
		tr[lc].add+=tr[p].add;
		tr[rc].add+=tr[p].add;
		tr[p].add=0;
	}
}
void build(int p,int l,int r){
	tr[p]={l,r,w[l],0};
	if(l==r) return;
	int m=l+r>>1;
	build(lc,l,m);
	build(rc,m+1,r);
	pushup(p);
}
void update(int p,int x,int y,int k){
	if(x<=tr[p].l&&tr[p].r<=y){
		tr[p].var+=k;
		tr[p].add+=k;
		return;
	}
	int m=tr[p].l+tr[p].r>>1;
	pushdown(p);
	if(x<=m) update(lc,x,y,k);
	if(y>m) update(rc,x,y,k);
	pushup(p);
}
int query(int p,int x,int y){
	if(x<=tr[p].l&&tr[p].r<=y){
		return tr[p].var;
	}
	int m=tr[p].l+tr[p].r>>1;
	pushdown(p);
	int ans=0x3f3f3f3f3f3f3f3f;
	if(x<=m) ans=min(ans,query(lc,x,y));
	if(y>m) ans=min(ans,query(rc,x,y));
	return ans;
}
signed main(){
	cin>>n>>q;
	for(int i=1;i<=n-1;i++) cin>>w[i];
	build(1,1,n-1);
	for(int i=1;i<=q;i++){
		int l,r;cin>>l>>r;
		if(l>r) swap(l,r);
		e[i]={l,r};
	} 
	sort(e+1,e+1+q);
	for(int i=1;i<=q;i++){
		int l=e[i].l+1,r=e[i].r;
		int num=query(1,l,r);
		if(num>0){
			ans+=num;
			update(1,l,r,-num);
		}
	}
	cout<<ans<<endl;
	return 0;
}

L3-020 至多删三个字符

在这里插入图片描述

#include<bits/stdc++.h>
using namespace std;
const int N=1e6+10;
#define int long long
typedef long long ll;
char s[N];
int f[N][4];//内存最好不要多开,4换成10就会内存超限

signed main(){
    cin>>s+1;
    int len=strlen(s+1);
    for(int i=0;i<=len;i++) f[i][0]=1;
    for(int i=1;i<=len;i++){
        for(int j=1;j<=3;j++){
            f[i][j]=f[i-1][j]+f[i-1][j-1];
            for(int k=i-1;k&&(i-k)<=j;k--){
                if(s[i]==s[k]){
                    f[i][j]-=f[k-1][j-(i-k)];
                    break;//这个不要忘记
                }
            }
        }
    }
    ll ans=f[len][0]+f[len][1]+f[len][2]+f[len][3];
    cout<<ans;
    return 0;
}

L3-021 神坛

在这里插入图片描述

#include<bits/stdc++.h>
using namespace std;
const int N=5e4+10;
typedef long long ll;
ll ans=1e17;
int n,i,cnt;
typedef pair<ll,ll> pll;

bool cmp(pll a,pll b){
    if(a.first*b.second!=b.first*a.second){
        return a.first*b.second>a.second*b.first;
    }
    return a.first<b.first;
}
int main(){
    cin>>n;
    vector<pll> a(n),b(n-1);
    for(int i=0;i<n;i++) cin>>a[i].first>>a[i].second;
    for(int i=0;i<n;i++,cnt=0){
        for(int j=0;j<n;j++){
            if(i==j) continue;
            b[cnt++]={a[j].first-a[i].first,a[j].second-a[i].second};
        }
        sort(b.begin(),b.end(),cmp);
        for(int j=1;j<n-1;j++) ans=min(ans,abs(b[j-1].first*b[j].second-b[j].first*b[j-1].second));
    }
    printf("%.3lf",0.5*ans);
    return 0;
}

L3-022 地铁一日游

在这里插入图片描述
在这里插入图片描述

#include<bits/stdc++.h>
using namespace std;
const int N=2050,M=60000,inf=0x3f3f3f3f;
typedef long long ll;
int n,m,k,cnt,x,tot;
int flag[M];
int t[M],d[N][N];
int g[N][N];
string s;
bool st[N];
set<int> se;

void floyed(){
	for(int i=1;i<=n;i++) d[i][i]=0;
	for(int k=1;k<=n;k++)
		for(int i=1;i<=n;i++)
			for(int j=1;j<=n;j++)
				d[i][j]=min(d[i][j],d[i][k]+d[k][j]);
}

void dfs(int u){
	st[u]=1;
	se.insert(u);
	for(int v=1;v<=n;v++){
		if(!st[v]&&g[u][v]){
			dfs(v);
		}
	}
}
int main(){
	cin>>n>>m>>k;
	memset(d,0x3f,sizeof d);
	getchar();
	while(m--){
		getline(cin,s);
		stringstream ss;
		ss<<s;
		cnt=0;//chushihua
		while(ss>>s){
			t[++cnt]=stoi(s);
		}
		for(int i=1;i<cnt;i+=2){
			int a=t[i],b=t[i+2],c=t[i+1];
			if(i==1) flag[a]=1;
			if(i==cnt-2) flag[b]=1;//这个地方的tot没有换成cnt过不了三个测试点
			d[b][a]=d[a][b]=min(d[a][b],c);
		}
	}
	floyed();
	for(int i=1;i<=n;i++){
		map<int,int> mp;
		for(int j=1;j<=n;j++){
			if(d[i][j]==inf) continue;
			int p=d[i][j]/k;
			mp[p]=max(mp[p],d[i][j]);
		}
		for(int j=1;j<=n;j++){
			int p=d[i][j]/k;
			if(i==j||d[i][j]==inf) continue;
			if(flag[j]||d[i][j]==mp[p]) g[i][j]=1;
		}
		g[i][i]=1;
	}
	cin>>m;
	
	while(m--){
		memset(st,false,sizeof st);
		se.clear();
		cin>>x;
		dfs(x);
		cout<<*se.begin();
		se.erase(*se.begin());
		for(auto x:se){
			cout<<" "<<x;
		}
		cout<<endl;
	}
    return 0;
}

L3-025 那就别担心了

在这里插入图片描述
在这里插入图片描述

#include<bits/stdc++.h>
using namespace std;
const int N=510;
bool flag;
int num[N];
int n,m;
vector<int> v[N];
int dfs(int u){
	if(num[u]) return num[u];
	for(auto x:v[u]){
		if(num[x]==0)
			dfs(x);
        num[u]+=num[x];//bunengfangdaoifxunhuannei
	}
    if(num[u]==0) flag=true;
	return num[u];
}
int main(){
	cin>>n>>m;
	while(m--){
		int a,b;cin>>a>>b;
		v[a].push_back(b);
	}
	int a,b;
	cin>>a>>b;
	num[b]=1;
	dfs(a);
	cout<<num[a]<<" "<<(flag?"No":"Yes");
    return 0;
}

L3-028 森森旅游

在这里插入图片描述
在这里插入图片描述

#include<bits/stdc++.h>
#define debug(x) cout<<#x<<" = "<<x<<endl
#define int long long
using namespace std;
typedef long long ll;
typedef pair<ll,int> pli;
const ll N=1e6 ,inf=0x3f3f3f3f3f3f3f3f;
int e[N],ne[N],h[N],rh[N],w[N],idx;
ll d1[N],d2[N],a[N];//记得long long
bool st[N];

void add(int h[],int a,int b,int c){
	e[idx]=b,ne[idx]=h[a],w[idx]=c,h[a]=idx++;
}

int n,m,q,u,v,c,d;
multiset<ll> se;

void dj(int h[],int s,ll d[]){
	memset(d,0x3f,sizeof d1);//不能是sizeof d,因为d只是个形参,表示数组第一个元素
    memset(st,0,sizeof st);
    // fill(d,d+N,inf);
    // fill(st,st+N,0);
	
	d[s]=0;
	priority_queue<pli,vector<pli>,greater<pli> > q;
	q.push({0,s});
	while(q.size()){
		auto t=q.top().second;
		q.pop();
		if(st[t]) continue;
		st[t]=true;
		for(int i=h[t];~i;i=ne[i]){
			int j=e[i];
			if(d[j]>d[t]+w[i]){
				d[j]=d[t]+w[i];
                q.push({d[j],j});
			}
		}
		
	}
	return;
}

signed main(){
	memset(h,-1,sizeof h);
	memset(rh,-1,sizeof rh);
	cin>>n>>m>>q;
	while(m--){
		cin>>u>>v>>c>>d;
		add(h,u,v,c),add(rh,v,u,d);
	}
	for(int i=1;i<=n;i++) cin>>a[i];
	dj(h,1,d1),dj(rh,n,d2);
    
	// for(int i=1;i<=n;i++) debug(d1[i]);
 //    cout<<endl;
 //    for(int i=1;i<=n;i++) debug(d2[i]);
    
	for(int i=1;i<=n;i++){
        if(d1[i]==inf||d2[i]==inf) continue;
		ll p=d1[i]+(d2[i]+a[i]-1)/a[i];
		se.insert(p);
	}
	while(q--){
		int x,y;cin>>x>>y;
        if(d1[x]==inf||d2[x]==inf){//两个一个到不了都不行
            cout<<*se.begin()<<endl;
            continue;
        }
		ll p=d1[x]+(d2[x]+a[x]-1)/a[x];
		se.erase(se.find(p));
		a[x]=y;
		p=d1[x]+(d2[x]+a[x]-1)/a[x];
		se.insert(p);
		cout<<*se.begin()<<endl;
	}
	return 0;
}

L3-029 还原文件

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

#include<bits/stdc++.h>
using namespace std;
const int N=1e6+10;
int n,m,k,t,flag1,flag2;
int h[N],st[N];

vector<int> ans,temp[101];

void dfs(int p){
    if(ans.size()==m){
        flag1=true;
        for(int i=0;i<m;i++){
            if(i) cout<<" ";
            cout<<ans[i];
        }
    }
    if(flag1) return;
    for(int i=1;i<=m;i++){
        if(st[i]) continue;
        flag2=0;
        for(int j=0;j<temp[i].size();j++){
            if(temp[i][j]!=h[p+j]){
                flag2=true;
                break;
            }
        }
        if(flag2) continue;
        ans.push_back(i);
        st[i]=true;
        dfs(p+temp[i].size()-1);
        st[i]=false;
        ans.pop_back();
    }
}
int main(){
    cin>>n;
    for(int i=0;i<n;i++) cin>>h[i];
    cin>>m;
    for(int i=1;i<=m;i++){
        cin>>k;
        for(int j=0;j<k;j++){
            cin>>t;
            temp[i].push_back(t);
        }
    }
    dfs(0);
    return 0;
}

L3-031 千手观音

在这里插入图片描述
在这里插入图片描述

#include<bits/stdc++.h>
using namespace std;
const int N=100010;

unordered_map<string,int> d;
unordered_map<string,vector<string>> g;
vector<string> get(string str){
    vector<string> res;
    string word;
    for(auto &c:str){
        if(c=='.'){
            res.push_back(word);
            if(!d.count(word)) d[word]=0;
            word="";
        }
        else word+=c;
    }
    res.push_back(word);
    if(!d.count(word)) d[word]=0;
    return res;
}
vector<string> topsort(){
    priority_queue<string,vector<string>,greater<string> > q;
    for(auto &[k,v]:d)
        if(!v)
            q.push(k);
    vector<string> res;
    while(q.size()){
        string t=q.top();q.pop();
        res.push_back(t);
        for(auto &p:g[t])
            if(--d[p]==0){
                q.push(p);
            }
    }
    return res;
}
int main(){
    ios::sync_with_stdio(false);
    int n;cin>>n;
    string str;cin>>str;
    vector<string> last=get(str);

    for(int i=0;i<n-1;i++){
        cin>>str;
        vector<string> cur=get(str);
        if(last.size()==cur.size()){
            for(int j=0;j<cur.size();j++)
                if(last[j]!=cur[j]){
                    g[last[j]].push_back(cur[j]);
                    d[cur[j]]++;//入度
                    break;
                }
        }
        last=cur;
    }
    vector<string> res=topsort();
    cout<<res[0];
    for(int i=1;i<res.size();i++)
        cout<<"."<<res[i];
    return 0;
}

L3-032 关于深度优先搜索和逆序对的题应该不会很难吧这件事

在这里插入图片描述
在这里插入图片描述

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N=3e5+10,p=1e9+7;

vector<int> g[N];
int sz[N],tr[N];
int n,root;
int sum=1,s1,s2;

void add(int x,int y){
    for(int i=x;i<N;i+=(i&-i))
        tr[i]+=y;
}
int query(int x){
    int res=0;
    for(int i=x;i;i-=(i&-i))
        res+=tr[i];
    return res;
}

void dfs(int u,int fa){
    add(u,1);
    s1=(s1+query(n)-query(u))%p;
    sz[u]=1;
    int cnt=0;
    for(auto &j:g[u]){
        if(j==fa) continue;
        dfs(j,u);
        sz[u]+=sz[j];
        cnt++;
    }
    for(int i=1;i<=cnt;i++)
        sum=(ll)sum*i%p;
    s2=(s2+n-query(n)-sz[u]+1)%p;
    add(u,-1);
}

int main(){
    cin>>n>>root;
    for(int i=0;i<n-1;i++){
        int a,b;cin>>a>>b;
        g[a].push_back(b);
        g[b].push_back(a);
    }
    dfs(root,-1);
    int ans=((ll)s1*sum+(ll)s2*sum%p*(p+1)/4)%p;
    cout<<ans;
    return 0;
}

L3-037 夺宝大赛

在这里插入图片描述

#include<bits/stdc++.h>
#define x first
#define y second
using namespace std;
const int N=110;
int g[N][N];
typedef pair<int,int> pii;

int n,m;
int ax,ay,d[N][N];
int dx[]={0,1,0,-1},dy[]={1,0,-1,0};
bool st[N][N];

vector<pii> ve;//或者直接用vector<vector<int>>
multiset<int> s;

void bfs(int x,int y){
    queue<pii> q;
    q.emplace(x,y);
    memset(d,0x3f,sizeof d);
    d[x][y]=0;
    while(q.size()){
        auto t=q.front();
        q.pop();
        for(int i=0;i<4;i++){
            int tx=t.x+dx[i],ty=t.y+dy[i];
            if(tx<1||tx>n||ty<1||ty>m||g[tx][ty]==0) continue;
            if(d[tx][ty]>d[t.x][t.y]+1){
                d[tx][ty]=d[t.x][t.y]+1;
                q.emplace(tx,ty);
            }
        }
    }
}
int main(){
    cin>>n>>m;
    for(int i=1;i<=n;i++){
        for(int j=1;j<=m;j++){
            cin>>g[i][j];
            if(g[i][j]==2){
                ax=i,ay=j;
            }
        }
    }
    int q;cin>>q;
    bfs(ax,ay);
    for(int i=0;i<q;i++){
        int x,y;
        cin>>y>>x;
        ve.emplace_back(d[x][y],i+1);
        s.insert(d[x][y]);
    }
    sort(ve.begin(),ve.end());
    bool f=false;
    for(int i=0;i<ve.size();i++){
        int dis=ve[i].x,id=ve[i].y;
        if(s.count(dis)==1&&dis!=0x3f3f3f3f){
            cout<<id<<" "<<dis<<endl;
            f=true;
            break;
        }
    }
    if(!f) cout<<"No winner.";
    return 0;
}
  • 4
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值