天梯训练L3

肿瘤诊断

题目大意就是给一个三维的01图,求这张01图中构成大于等于T的连通块的1的总数。

bfs  搜索

 1 #include<bits/stdc++.h>
 2 using namespace std;
 3 const int MAXN = 1e5+10;
 4 inline int read(){
 5     int c=0, f=1;  char ch = getchar();
 6     while (ch<'0'||ch>'9'){ if(ch=='-') f = -1; ch = getchar(); }
 7     while (ch>='0'&&ch<='9'){ c = c*10+ch-'0'; ch = getchar();}
 8     return c*f;
 9 }
10 int n, m, l, t, ans = 1;
11 bool mp[70][1300][130];
12 int dx[] = {1, -1, 0, 0, 0, 0};
13 int dy[] = {0, 0, 1, -1, 0, 0};
14 int dz[] = {0, 0, 0, 0, 1, -1};
15 struct node
16 {
17     int x, y, z;
18 };
19 
20 int bfs(int x,int y,int z){
21     mp[x][y][z] = 0;
22     queue<node> q;
23     int res = 0;
24     q.push((node){x, y, z});
25     while (!q.empty())
26     {
27         node fa = q.front();
28         q.pop();
29         ++res;
30         for(int i = 0;i < 6;i ++){
31             int nx = fa.x + dx[i];
32             int ny = fa.y + dy[i];
33             int nz = fa.z + dz[i];
34             if(!nx|| nx>l|| !ny|| ny>m|| !nz|| nz>n) continue;
35             if(mp[nx][ny][nz]){
36                 mp[nx][ny][nz] = 0;
37                 q.push((node){nx, ny, nz});
38             }
39         }
40     }
41     return res;
42 }
43 
44 int main()
45 {   
46     m = read();  n = read();  l = read();  t = read();
47     for(int i=1;i<=l;i++){
48         for(int j=1;j<=m;j++){
49             for(int k=1;k<=n;k++){
50                 mp[i][j][k] = read();
51             }
52         }
53     }
54     int sum = 0;
55     for(int i=1;i<=l;i++){
56         for(int j=1;j<=m;j++){
57             for(int k=1;k<=n;k++){
58                 if(mp[i][j][k]){
59                     ans = bfs(i,j,k);
60                     if(ans>=t) sum += ans;
61                 }
62             }
63         }
64     }
65     cout<<sum;
66     return 0;
67 }
laji Code

特殊堆栈

题目大意就是实现三种操作,分别为出栈,入栈,取中值。

思路1:

因为堆栈是无序的,在堆栈中查找中值非常的麻烦,所以考虑开多一个数组进行排序,排序后中值就是n+1/2的位置;

因为是依次给出的操作,所以选择使用二分插入排序维护有序数组;

而普通的数组进行插入排序难以实现,所以选择动态数组vector;

使用一个数组用作堆栈进行出栈入栈操作,一个动态数组为堆栈元素的有序数组进行取中值操作;

 

vector的基本操作:https://blog.csdn.net/wkq0825/article/details/82255984

#include<algorithm> 中二分查找函数的使用:https://blog.csdn.net/jadeyansir/article/details/77015626

 1 #include<bits/stdc++.h>
 2 
 3 using namespace std;
 4 int t,tmp;
 5 string op;
 6 vector<int> stk,a;
 7 
 8 int main()
 9 {
10     cin>>t;
11     while(t--){
12         cin>>op;
13         if(op == "Push"){
14             //入栈 
15             cin>>tmp;
16             stk.push_back(tmp);
17             a.insert(upper_bound(a.begin(),a.end(),tmp),tmp);
18         }
19         else if(op == "Pop"){
20             //出栈 
21             if(!stk.size())  cout<<"Invalid\n";
22             else{
23                 tmp = stk[stk.size()-1];
24                 cout<<tmp<<endl;
25             
26                 stk.pop_back();
27                 a.erase(lower_bound(a.begin(),a.end(),tmp)); 
28             }
29                 
30         }
31         else if(op == "PeekMedian"){
32             //取中值
33             tmp = a.size();
34             if(!tmp)  cout<<"Invalid\n";
35             else{
36                 if(tmp&1){
37                     cout<<a[tmp/2]<<endl;
38                 }
39                 else
40                     cout<<a[tmp/2-1]<<endl;
41             }
42         }
43     }
44     return 0;
45 }
laji Code

思路2:

取中值操作也就是找一个第k小的数,k=n+1/2;

对于第k小的数,说明k的左边有n+1/2-1个数,右边有n+1/2+1个数。

那就可以二分查找一个值t,若这个t符合左边有第k小数性质的话,说明就是答案。

那么如何快速的知道数值t的左右两个区间【1,t】【t,1e5】的元素个数呢,可以用线段树或树状数组维护区间【1,1e5】中每个整数在序

列中出现的次数,从而快速的更新和查找区间【l,r】的元素个数。

#include<bits/stdc++.h>
#define MAXN 100010
#define inf 100000
#define lson rt<<1
#define rson rt<<1|1
using namespace std;
int sum[MAXN*4]; 
int n,tot=0,stk[MAXN],mx,t,tmp;
string op;

void add(int l,int r,int rt,int k,int val){
    if(l==k && r==k){
        sum[rt] += val;
        return ;
    }
    int mid = (l+r)>>1;
    if(mid>=k)
        add(l,mid,lson,k,val);
    else 
        add(mid+1,r,rson,k,val);

    sum[rt] = sum[lson]+sum[rson];
    return ;
}

int fid(int l,int r,int rt,int ul,int ur){
    if(ul<=l && r<=ur){
        return sum[rt];
    }
    int ans = 0;
    int mid = (l+r)>>1;
    if(ul<=mid)  ans += fid(l,mid,lson,ul,ur);
    if(ur>mid)  ans += fid(mid+1,r,rson,ul,ur);
    return ans;
}
int getmid(int x){
    int l = 1, r = mx;
    while(l<r){
        int mid = (l+r)>>1;
        int num = fid(1,inf,1,1,mid);

        if(num>=x) r = mid;
        else l = mid+1;
    }
    return l;
}

int main()
{
    cin>>t;
    while(t--){
        cin>>op;
        if(op == "Push"){
            //入栈 
            cin>>tmp;
            stk[++tot] = tmp;
            mx = max(tmp,mx);
            add(1,inf,1,tmp,1);
        }
        else if(op == "Pop"){
            //出栈 
            if(!tot) cout<<"Invalid\n";
            else{
                add(1,inf,1,stk[tot--],-1);
                cout<<stk[tot+1]<<endl;
            }   
        }
        else if(op == "PeekMedian"){
            //取中值
            if(!tot) cout<<"Invalid\n";
            else{
                tmp = (tot+1)>>1;
                cout<<getmid(tmp)<<endl;
            }
        }
    }
    return 0;
 } 
laji Code

 天梯地图

题目链接:https://pintia.cn/problem-sets/994805046380707840/problems/994805051153825792

题目大意:在图中找两条路径,一条路径使得起点到终点的距离最短,如果有距离一样短的其他路径则输出结点数最少的路径,另一条路径是

使得起点到终点的时间最短,如果有时间一样短的路径则输出距离最短的路径;

以距离为权值求一次单源最短路;

以时间为权值求一次单源最短路;

最后判断一下路径是否相同即可;

#include <bits/stdc++.h>
using namespace std;
const int N=505,INF=0x3f3f3f3f;
int n,m;
struct edg{
    int to,w,l;
}E1,E2;  
vector<edg>G[N],T[N];
int dis[N],pre[N],vis[N],in[N],num[N],out[N];
int diss[N],sum[N];
struct Node{
    int to,w;
    bool operator <(const Node&x)const{
        return x.w<w;
    }
}p,q;
void printff(vector<int> vec){
    int flag=0;
    for(int i=vec.size()-1;i>=0;i--){
        if(flag) cout << " => ";
        cout << vec[i],flag=1;
    }
    cout << endl;
}
int judge(vector<int>vec,vector<int>vec1){
    if(vec.size()!=vec1.size()) return 0;
    for(int i=0;i<vec.size();i++)
        if(vec[i]!=vec1[i]) return 0;  
    return 1;
}
void dij1(int start){
    priority_queue<Node> que;
    for(int i=0;i<=N-1;i++) dis[i]=INF,pre[i]=-1,vis[i]=0;
    que.push({start,0}),dis[start]=0,num[start]=1;
    while(!que.empty()){
        p=que.top(),que.pop();
        int u=p.to,v,w,z;
        if(vis[u]) continue;
        vis[u]=1;
        for(auto X:G[u]){
            v=X.to,w=X.w,z=1;
            if(dis[v]>w+p.w)
                dis[v]=w+p.w,pre[v]=u,num[v]=num[u]+1,q.to=v,q.w=dis[v],que.push(q);
            else if(dis[v]==w+p.w){
                if(num[v]>num[u]+1)  
                    num[v]=num[u]+1,pre[v]=u;
            }
        }
    }
}
void dij2(int start)    
{
    priority_queue<Node> que;
    for(int i=0;i<=N-1;i++) pre[i]=-1,vis[i]=0,sum[i]=INF,diss[i]=0;
    que.push({start,0}),diss[start]=0,sum[start]=0; 
    while(!que.empty()){
        p=que.top(),que.pop();
        int u=p.to,v,w,z;
        if(vis[u]) continue;
        vis[u]=1;
        for(auto X:G[u]){
            v=X.to,w=X.w,z=X.l;  
            if(sum[v]>z+p.w)
                sum[v]=z+p.w,pre[v]=u,diss[v]=diss[u]+w,q.to=v,q.w=sum[v],que.push(q);
            else if(sum[v]==z+p.w){
                if(diss[v]>diss[u]+w)  
                    diss[v]=diss[u]+w,pre[v]=u;
            }
        }
    }
}

int main()
{
    ios::sync_with_stdio(false);
    cin>>n>>m;
    for(int i=0,d1,d2,d3,d4,d5;i<m;i++){
        cin>>d1>>d2>>d3>>d4>>d5;
        G[d1].push_back({d2,d4,d5}); 
        if(!d3){
            G[d2].push_back({d1,d4,d5});
        }
    }
    vector<int> vec,vec1;
    int start,ending;
    cin>>start>>ending;
    dij2(start);     
    int pos=ending;
    while(pos!=-1) vec.push_back(pos),pos=pre[pos]; 
    dij1(start);
    
    pos=ending;
    while(pos!=-1) vec1.push_back(pos),pos=pre[pos];
    
    if(judge(vec,vec1))
        cout<<"Time = "<<sum[ending]<<"; "<<"Distance = "<<dis[ending]<<": ",printff(vec);
    else{
        cout << "Time = " << sum[ending] <<": ";
        printff(vec);
        cout << "Distance = " << dis[ending] <<": ";
        printff(vec1);
    }
    return 0;
}
laji Code
posted @ 2021-01-24 14:01  面向题目编程  阅读(119)  评论(0)    收藏  举报