3.18 - 3.24 周记

Posted 1625--h

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了3.18 - 3.24 周记相关的知识,希望对你有一定的参考价值。

3.18-3.24

2.天梯赛练习集-L2部分

L2-001?紧急救援

比较裸的一个迪杰斯特拉,更新的时候需要考虑更多的信息

当由 x 更新结点 y 时。

  1. d[y]更新时,到达被y的路径条数变为 x 的路径条数,y人数随之更新
  2. d[y] = d[x]+ dis[x][y]相等时,y结点路径条数增加,人数却要与之前的做比较,取一个最大值。
#include <bits/stdc++.h>
using namespace std;
const int N = 550,M = N*N;
const int inf = 0x3f3f3f3f;
int a[N],d[N],f[N],g[N],pa[N],n,m,s,e;
int vis[N];
int ver[M],edge[M],head[N],nxt[M],tot;
void add(int x,int y,int z){
    ver[++tot] = y;
    edge[tot] = z;
    nxt[tot] = head[x];
    head[x] = tot;
}
void print(int now){
    if(now==pa[now])printf("%d",now-1);
    else{
        print(pa[now]);
        printf(" %d",now-1);
    }
}
int main(){
    cin>>n>>m>>s>>e;
    s++;e++;
    for(int i=1;i<=n;i++){
        scanf("%d",&a[i]);
        g[i] = a[i];
    }
    for(int i=1;i<=m;i++){
        int x,y,z;
        scanf("%d%d%d",&x,&y,&z);
        x++;y++;
        if(x==y)continue;
        add(x,y,z);
        add(y,x,z);
    }
    for(int i=1;i<=n;i++)d[i] = inf;
    d[s] = 0;f[s] = 1;g[s] = a[s],pa[s] = s;
    for(int i=0;i<n;i++){
        int id = inf;
        for(int j=1;j<=n;j++)
            if(!vis[j]&&(id==inf||d[j]<d[id]))id = j;
        vis[id] = 1;
        if(id==e)break;
        for(int j=head[id];j;j = nxt[j]){
            int y = ver[j];
            if(vis[y])continue;
            if(d[y] == d[id]+edge[j]){
                f[y] += f[id];
                if(g[y]<=g[id]+a[y]){
                    g[y] = g[id]+a[y];
                    pa[y] = id;
                }
            }
            else if(d[y]>d[id]+edge[j]){
                f[y] = f[id];
                g[y] = a[y]+g[id];
                d[y] = d[id]+edge[j];
                pa[y] = id;
            }
        }
    }
    printf("%d %d
",f[e],g[e]);
    print(e);
    puts("");
    return 0;
}

L2-007?家庭房产

  • 一道挺恶心的并查集,匆匆过了
#include <bits/stdc++.h>
using namespace std;
const int N = 1010,M = 10010;
int fa[M],vis[M];
int find(int x){
    return x==fa[x]?x:fa[x] = find(fa[x]);
}
vector<int> g[M];
struct node{
    int num;
    int id;
    int cnt;
    int flag;
    double sum;
    double ave;
    double ave_num;
}a[M],b[M];
int n;
void merge(int x,int y){
    x = find(x);
    y = find(y);
    if(x>y)swap(x,y);
    fa[y] = x;
}
bool cmp(node a,node b){
    if(a.ave==b.ave){
        return a.id<b.id;
    }
    return a.ave>b.ave;
}
int main(){
    cin>>n;
    for(int i=0;i<=10000;i++){
        fa[i] = i;
        a[i].cnt = 1;
        a[i].id = i;
    }
    for(int i=1;i<=n;i++){
        int id,father,mather,k;
        cin>>id>>father>>mather>>k;
        vis[id] = 1;
        if(father!=-1){
            merge(id,father);
            vis[father] = 1;
        }
        if(mather!=-1){
            merge(id,mather);
            vis[mather] = 1;
        }
        for(int j=0;j<k;j++){
            int x;
            cin>>x;
            merge(id,x);
            vis[x] = 1;
        }
        cin>>a[id].num>>a[id].sum;
    }
    for(int i=0;i<10000;i++){
        if(vis[i]){
            int x = find(i);
            b[x].sum += a[i].sum;
            b[x].num += a[i].num;
            b[x].cnt ++;
            b[x].flag = 1;
            b[x].id = x;
        }
    }
    int res = 0;
    for(int i=0;i<10000;i++){
        if(b[i].flag){
            if(b[i].num){
                b[i].ave = b[i].sum/b[i].cnt;
                b[i].ave_num = b[i].num/b[i].cnt;
                b[i].ave = (double)round(b[i].ave*1000.0)/1000;
            }
            else{
                b[i].ave = 0;
                b[i].ave_num = 0;
            }

            res++;
            //printf("%d %d %d %lf
",i,b[i].id,b[i].num,b[i].ave);
        }
    }
    sort(b,b+10000,cmp);
    cout<<res<<endl;
    for(int i=0;i<res;i++){
        printf("%04d %d %.3lf %.3lf
",b[i].id,b[i].cnt,(double)b[i].num/b[i].cnt,b[i].ave);
    }
    return 0;
}

L2-014

  • 为了保证最后的出队序列是有序的,那么每个小队列也必须是有序的,最少的递减序列条数等于最长的单调不减序列的长度。所以直接求最长的单调不减序列长度即可。二分解法中每次覆盖之前的值,就可以理解为增加这一个位置纵向上的递减序列长度(比较抽象)
#include <bits/stdc++.h>
using namespace std;
const int N = 100010;
int a[N],dp[N];
int n;
int main(){
    cin>>n;
    for(int i=1;i<=n;i++)scanf("%d",&a[i]);
    int len = 0;
    for(int i=1;i<=n;i++){
        int pos = lower_bound(dp,dp+len,a[i])-dp;
        if(pos<len)dp[pos] = a[i];
        else dp[len++] = a[i];
    }
    cout<<len<<endl;
    return 0;
}

L2-023?图着色问题

  • 这个题很单纯,所用颜色必须为k个,多一个少一个都不行
#include <bits/stdc++.h>
using namespace std;
const int N = 1010;
int a[N];
int n,m,k,t;
struct edge{
    int x,y;
}eg[N*N];
bool check(){
    for(int i=1;i<=m;i++){
        if(a[eg[i].x]==a[eg[i].y])return false;
    }
    return true;
}
int main(){
    cin>>n>>m>>k;
    for(int i=1;i<=m;i++){
        scanf("%d%d",&eg[i].x,&eg[i].y);
    }
    cin>>t;
    set<int> st;
    while(t--){
        st.clear();
        for(int i=1;i<=n;i++){
            scanf("%d",&a[i]);
            st.insert(a[i]);
        }
        //cout<<st.size()<<endl;
        if(st.size()!=k){
            puts("No");
        }
        else if(check()){
            puts("Yes");
        }
        else puts("No");
    }
    return 0;
}

3. 天梯赛练习集-L3部分

L3-001?凑零钱

  • 记忆路径的背包问题,因为要满足答案字典序最小,所以先从大的选,也可以理解为尽可能让小的有更多的选择,使得答案中字典序小的优先选取
#include <bits/stdc++.h>
using namespace std;
int dp[10004][102];
int a[10004];
int main() {
    ios::sync_with_stdio(false);
    int n, m;
    cin >> n >> m;
    for(int i = 1; i <= n; i++) {
        cin >> a[i];
    }
    sort(a + 1, a + n + 1, greater<int>()); // 保证字典序最小
    dp[0][0] = 1;
    for(int i = 1; i <= n; i++) {
        for(int j = 0; j <= m; j++) {
            dp[i][j] = dp[i - 1][j];
            if(j >= a[i])
                dp[i][j] += dp[i - 1][j - a[i]];
        }
    }
    if(dp[n][m] == 0) {
        cout << "No Solution";
    } else {
        vector<int> ans;
        int i = n, j = m;
        while(j > 0) {
            if(j - a[i] >= 0 && dp[i - 1][j - a[i]]>0) {
                ans.push_back(a[i]);
                j -= a[i];
            }
            i--;
        }
        cout << ans[0];
        for(int k = 1; k < ans.size(); k++) {
            cout << " " << ans[k];
        }
    }
}

L3-002?特殊堆栈

  • 线段树
  • 二分
#include <bits/stdc++.h>
using namespace std;
const int N = 100010;
//maintain the number of values between the l and r
struct SegmentTree{
    int l,r;
    int dat;
    #define L(x) t[x].l
    #define R(x) t[x].r
    #define MID(x) (t[x].l+t[x].r)/2
}t[N*4];
int n;
void build(int p,int l,int r){
    t[p].l = l;t[p].r = r;
    t[p].dat = 0;
    if(l==r)return;
    build(p*2,l,MID(p));
    build(p*2+1,MID(p)+1,r);
    t[p].dat = t[p*2].dat+t[p*2+1].dat;
}
void change(int p,int x,int v){
    if(L(p)==R(p)&&L(p)==x){
        t[p].dat += v;
        return ;
    }
    if(x<=MID(p)) change(p*2,x,v);
    else change(p*2+1,x,v);
    t[p].dat = t[p*2].dat+t[p*2+1].dat;
}
int query(int p,int x){
    if(L(p)==R(p))return R(p);
    if(x<=t[p*2].dat)return query(p*2,x);
    else return query(p*2+1,x-t[p*2].dat);
}
int st[N];
char op[15];
int main(){
    cin>>n;
    int top = 0;
    build(1,1,N-10);
    while(n--){
        scanf("%s",op);
        if(op[1] == 'o'){
            if(top==0)puts("Invalid");
            else{
                cout<<st[--top]<<endl;
                change(1,st[top],-1);
            }
        }
        else if(op[1]=='u'){
            int x;
            scanf("%d",&x);
            st[top++] = x;
            change(1,st[top-1],1);
            //cout<<x<<endl;
        }
        else{
            if(top==0)puts("Invalid");
            else{
                cout<<query(1,(top+1)/2)<<endl;
            }
        }
    }
    return 0;
}
#include <bits/stdc++.h>
using namespace std;
const int N = 100010;
vector<int> v;
int st[N],top;
int n,x;
char op[15];
int main(){
    cin>>n;
    while(n--){
        scanf("%s",op);
        if(op[1]=='o'){
            if(top==0)puts("Invalid");
            else{
                printf("%d
",st[--top]);
                int p = lower_bound(v.begin(),v.end(),st[top])-v.begin();
                v.erase(v.begin()+p);
            }
        }
        else if(op[1]=='u'){
            scanf("%d",&x);
            st[top++] = x;
            int p = lower_bound(v.begin(),v.end(),x)-v.begin();
            v.insert(v.begin()+p,x);
        }
        else{
            if(top==0)puts("Invalid");
            else
            printf("%d
",v[(top-1)/2]);   
        }
    }
    return 0;
}

L3-004?肿瘤诊断

  • 三维BFS ,如果用DFS会爆栈
#include <bits/stdc++.h>
using namespace std;
int ma[1300][200][100];
int vis[1300][200][100];
int m,n,l,t;
int dx[6] = {1,-1,0,0,0,0};
int dy[6] = {0,0,1,-1,0,0};
int dz[6] = {0,0,0,0,1,-1};
bool check(int x,int y,int z){
    if(x<1||x>m||y<1||y>n||z<1||z>l)return false;
    if(vis[x][y][z]||ma[x][y][z]==0)return false;
    return true;
}
struct node{
    int x,y,z;
};
int bfs(int x,int y,int z){
    queue<node> q;
    int res = 0;
    q.push({x,y,z});vis[x][y][z] = 1;
    while(!q.empty()){
        node u = q.front();q.pop();
        res++;
        for(int i=0;i<6;i++){
            int a = u.x+dx[i];
            int b = u.y+dy[i];
            int c = u.z+dz[i];
            if(check(a,b,c)){
                q.push({a,b,c});
                vis[a][b][c] = 1;
            }
        }
    }  
    return res;
}
int main(){
    //memset(vis,0,sizeof vis);
    scanf("%d%d%d%d",&m,&n,&l,&t);
    for(int i=1;i<=l;i++){
        for(int x=1;x<=m;x++){

            for(int y=1;y<=n;y++){
                vis[x][y][i]=0;
                scanf("%d",&ma[x][y][i]);
            }
        }
    }
    int res = 0;
    for(int z=1;z<=l;z++){
        for(int x=1;x<=m;x++){
            for(int y=1;y<=n;y++){
                if(ma[x][y][z]==1&&vis[x][y][z]==0){
                    int c = bfs(x,y,z);
                    //cout<<x<<endl;
                    if(c>=t)res+=c;
                }
            }
        }
    }
    cout<<res<<endl;
    return 0;
}

L3-007?天梯地图

  • 比较烦人的最短路,记录路径,比较路径,变量名上一定要细心
#include <bits/stdc++.h>
using namespace std;
const int N = 505;
const int inf = 0x3f3f3f3f;
int len[N][N],tim[N][N];
int n,m;
int d[N],t[N],g[N],vis[N],st,ed;
vector<int> t_res,d_res;
void get_tim(int x){
    if(x==st)t_res.push_back(x-1);
    else {
        get_tim(g[x]);
        t_res.push_back(x-1);
    }
}
void get_dis(int x){
    if(x==st)d_res.push_back(x-1);
    else{
        get_dis(g[x]);
        d_res.push_back(x-1);
    }
}
bool check(){
    if(d_res.size()!=t_res.size())return false;
    for(int i=0;i<d_res.size();i++)
        if(d_res[i] != t_res[i])return false;
    return true;
}
int main(){
    memset(len,0x3f,sizeof len);
    memset(tim,0x3f,sizeof tim);
    cin>>n>>m;
    for(int i=1;i<=m;i++){
        int x,y,one,l,t;
        cin>>x>>y>>one>>l>>t;
        x++;y++;
        len[x][y] = l;
        tim[x][y] = t;
        if(one == 0){
            len[y][x] = l;
            tim[y][x] = t;
        }
    }
    cin>>st>>ed;
    st++;ed++;
    for(int i=1;i<=n;i++)d[i] = inf,t[i] = inf,vis[i] = 0;
    d[st] = 0;t[st] = 0;
    priority_queue<pair<int,int> > q;
    q.push(make_pair(0,st));
    while(!q.empty()){
        int x = q.top().second;q.pop();
        if(vis[x])continue;
        vis[x] = 1;
        for(int i=1;i<=n;i++){
            if(i==x)continue;
            if(t[i] > t[x]+tim[x][i]){
                t[i] = t[x]+tim[x][i];
                d[i] = d[x]+len[x][i];
                g[i] = x;
                q.push(make_pair(-t[i],i));
            }
            else if(t[i]==t[x]+tim[x][i]&&d[i]>d[x]+len[x][i]){
                d[i] = d[x]+len[x][i];
                g[i] = x;
                q.push(make_pair(-t[i],i));
            }
        }
    }
    printf("Time = %d",t[ed]);
    get_tim(ed);
    for(int i=1;i<=n;i++)d[i] = inf,t[i] = inf,vis[i] = 0;
    d[st] = 0;t[st] = 1;
    q.push(make_pair(0,st));
    while(!q.empty()){
        int x = q.top().second;q.pop();
        if(vis[x])continue;
        vis[x] = 1;
        for(int i=1;i<=n;i++){
            if(i==x)continue;
            if(d[i] > d[x]+len[x][i]){
                d[i] = d[x]+len[x][i];
                t[i] = t[x]+1;
                g[i] = x;
                q.push(make_pair(-d[i],i));
            }
            else if(d[i] == d[x]+len[x][i]&&t[i] > t[x]+1){
                t[i] = t[x]+1;
                g[i] = x;
                q.push(make_pair(-d[i],i));
            }
        }
    }
    get_dis(ed);
    if(check()){
        printf("; Distance = %d: %d",d[ed],d_res[0]);
        for(int i=1;i<d_res.size();i++){
            printf(" => %d",d_res[i]);
        }
        puts("");
    }
    else{
        printf(": %d",t_res[0]);
        for(int i=1;i<t_res.size();i++)printf(" => %d",t_res[i]);
        puts("");
        printf("Distance = %d: %d",d[ed],d_res[0]);
        for(int i=1;i<d_res.size();i++){
            printf(" => %d",d_res[i]);
        }
        puts("");
    }
    return 0;
}

L3-016?二叉搜索树的结构

  • BST 例题
#include <bits/stdc++.h>
using namespace std;
const int N = 110;
struct node{
    int l,r,data,fa;
}t[N];
map<int,int> id;
int a[N],n,m,d[N];
void insert(int &p,int fa,int now,int x,int dp){
    if(p==-1){
        p = now;
        t[p].data = x;
        t[p].fa = fa;
        id[x] = now;
        d[now] = dp;
        return;
    }
    if(t[p].data>x)
        insert(t[p].l,p,now,x,dp+1);
    else insert(t[p].r,p,now,x,dp+1);
}
int main(){
    scanf("%d",&n);
    int root = -1;
    for(int i=1;i<=n;i++)t[i].data=t[i].l=t[i].r= -1;
    for(int i=1;i<=n;i++){
        scanf("%d",&a[i]);
        insert(root,-1,i,a[i],1);
    }  
    int q;cin>>q;
    string st;int a,b;
    while(q--){
        cin>>a;
        cin>>st;
        if(st=="is"){
            cin>>st>>st;
            if(st=="root"){
                if(!id.count(a)){
                    puts("No");continue;
                }
                if(id[a]==1)puts("Yes");
                else puts("No");
            }
            else if(st=="parent"){
                cin>>st>>b;
                if(!id.count(a)||!id.count(b)){
                    puts("No");continue;
                }
                if(t[id[b]].fa == id[a])puts("Yes");
                else puts("No");
            }
            else if(st=="left"){
                cin>>st>>st>>b;
                if(!id.count(a)||!id.count(b)){
                    puts("No");continue;
                }
                if(t[id[b]].l == id[a])puts("Yes");
                else puts("No");
            }
            else if(st=="right"){
                cin>>st>>st>>b;
                if(!id.count(a)||!id.count(b)){
                    puts("No");continue;
                }
                if(t[id[b]].r==id[a])puts("Yes");
                else puts("No");
            }
        }
        else{
            cin>>b;
            cin>>st>>st;
            if(st=="siblings"){
                if(!id.count(a)||!id.count(b)||a==b){
                    puts("No");continue;
                }
                if(t[id[a]].fa==t[id[b]].fa)puts("Yes");
                else puts("No");
            }
            else {
                cin>>st>>st>>st;
                if(!id.count(a)||!id.count(b)){
                    puts("No");continue;
                }
                if(d[id[a]] == d[id[b]])puts("Yes");
                else puts("No");
            }
        }
    }
    return 0;
}

L3-015?球队“食物链”

  • 状压dp
#include <bits/stdc++.h>
using namespace std;
int n;
char s[22][22];
int d[1<<20][22];
int g[22];
bool check(int st){
    int res = 0;
    while(st&1)res++,st>>=1;
    return res == n;
}
bool dp(int st,int fi,int now){
    if(check(st)){
        if(s[now][fi]=='W' || s[fi][now] == 'L'){
            g[fi] = now;
            return true;
        }
        else return false;
    }
    int flag = 0;
    for(int i=0;i<n;i++){
        if((st>>i)&1)continue;
        if(s[i][fi] == 'W'||s[fi][i] == 'L'){
            flag = 1;break;
        }
    }
    if(flag == 0)return false;
    for(int i=0;i<n;i++){
        if((st>>i)&1)continue;
        if(s[now][i]=='W' || s[i][now] == 'L'){
            g[i] = now;
            if(dp(st+(1<<i),fi,i))return true;
        }
    }
    return false;
}
void print(int x,int fi){
    if(x==fi)printf("%d",x+1);
    else{
        print(g[x],fi);
        printf(" %d",x+1);
    }
}
int main(){
    scanf("%d",&n);
    int num = 0;
    for(int i=0;i<n;i++){
        scanf("%s",s[i]);
    }
    for(int i=0;i<n;i++){
        if(dp(1<<i,i,i)){
            //for(int i=0;i<n;i++)printf("%d",g[i]);
            print(g[i],i);
            puts("");
            return 0;
        }
    }
    puts("No Solution");
    return 0;
}

L3-013?非常弹的球

  • 很骚的一个题,有高中物理知识可以推导出,当角度为45度时,路程最远。
#include <cstdio>
int main() {
    double w, p, v2, s = 0;
    scanf("%lf%lf", &w, &p);
    v2 = 2 * 1000 * 100 / w;
    while (v2 > 0.000001) {
        s += v2 / 9.8;
        v2 *= (100 - p) * 0.01;
    }
    printf("%.3f", s);
    return 0;
}

以上是关于3.18 - 3.24 周记的主要内容,如果未能解决你的问题,请参考以下文章

「学习笔记」3.24代码学习

「学习笔记」3.24代码学习

2018年自然语言处理及相关国际会议重要日期整理

3.24

学习(3.18)

第五周周记