2016年团体程序设计天梯赛-模拟赛

L2-1. 集合相似度

stl set模板,以后复习可以看一下,当模板用了,去重很有用呀

#include <cstdio>
#include <set>
using namespace std;
set<int> s[50];
int main(){
    //freopen("G:\input.in", "r", stdin);
    int n;
    scanf("%d", &n);
    for (int i = 0; i < n; ++i){
        int num, x;
        for (scanf("%d", &num); num; --num){
            scanf("%d", &x);
            s[i].insert(x);
        }
    }
    int k;
    for (scanf("%d", &k); k; --k){
        int a, b;
        scanf("%d%d", &a, &b);
        int counta = s[a - 1].size(), countb = s[b - 1].size();
        int cnt = 0;
        for (set<int>::iterator iter = s[a - 1].begin(); iter != s[a - 1].end(); ++iter){
            if (s[b - 1].find(*iter) != s[b - 1].end())
                cnt++;
        }
        printf("%.2lf%%
", cnt*1.0/(counta+countb-cnt)*100);
    }
    return 0;
}
set模板

L2-2. 树的遍历

已知后序和中序输出层次遍历

比如test的

7
2 3 1 5 7 6 4
1 2 3 4 5 6 7
思路:后序遍历按左右中的关系遍历,中序按左中右的关系遍历,所以后序遍历的最后一个4必然是整颗树的root,中序数组中的4前面的1 2 3必然是4(root)的左子树,1 2 3当作一个树,继续推导这颗树的root,(1 2 3)在后序数组可以确定root为1,在确定(1 2 3)树的左右子树..
然后可以发现这是一个递归的过程,我的方法是递归的恢复原来的这颗树,至于层次遍历,我是用queue实现的
#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <cmath>
#include <stack>
#include <queue>
#include <string>
#include <map>
#include <set>
#include <algorithm>

using namespace std;

const int inf = 0x3f3f3f;
const int MAXN = 3e1+10;

using namespace std;


struct tree{
    tree*l;
    tree*r;
    int d;
};

int L[MAXN],M[MAXN];
map<int ,int >mp;

tree* addnode(int d){
    tree*nt = (tree*)malloc(sizeof(tree));
    nt->d = d;
    nt->l = NULL;
    nt->r = NULL;
    return nt;
}

tree* dfs(int s,int e,int top){
    if(s>e)return NULL;
    if(s==e){
        return addnode(M[s]);
    }
    int mmax = 0,rootd;
    for(int i=s;i<=e;i++){
        if(mmax<mp[M[i]]){
            mmax = mp[M[i]];
            rootd = M[i];
        }
    }
    int mid;
    for(int i=s;i<=e;i++){
        if(M[i]==rootd){
            mid = i;
            break;
        }
    }
    tree*root = addnode(rootd);
    if(mid!=s)
        root->l = dfs(s,mid-1,2*top+1);
    if(mid!=e)
        root->r = dfs(mid+1,e,2*top+2);
    return root;
}

//queue实现层次遍历
void print(tree*root){
    queue<tree*>Q;
    Q.push(root);
    while(!Q.empty()){
        tree *tf;
        tf = Q.front();
        Q.pop();
        if(tf!=root)cout<<" ";
        cout<<tf->d;
        if(tf->l!=NULL)Q.push(tf->l);
        if(tf->r!=NULL)Q.push(tf->r);
    }
    cout<<endl;

}

void del(tree*root){
    if(!root)return;
    del(root->l);
    del(root->r);
    free(root);
}

int main()
{
    int n;
    while(scanf("%d",&n)!=EOF){
        for(int i=0;i<n;i++){
            scanf("%d",&L[i]);
            mp[L[i]] = i;
        }
        for(int i=0;i<n;i++){
            scanf("%d",&M[i]);
        }
        tree*root = dfs(0,n-1,0);
        print(root);
        del(root);
    }
    return 0;
}
View Code

L2-3. 家庭房产

裸并查集

0000~9999 节点都已经唯一确定,所以用一维数组做就好了,本来想用map<string,string>,输出方便一点,奈何gg了,不会改,输出了奇怪的东西,原来数组开小了,开了几个小时orz

#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <cmath>
#include <stack>
#include <string>
#include <queue>
#include <map>
#include <set>
#include <vector>
#include <algorithm>

const int inf = 0x3f3f3f;
const int MAXN = 1e4+10;

using namespace std;

struct fy{
    int npcid;
    int faid;
    int maid;
    int k;
    int sid[5];
    int n;
    int s;
};

struct rel{
    int minid;
    int tol;
    int n;
    int s;
    double pern;
    double pers;
};

int father[MAXN];
int mark[MAXN];
fy a[MAXN];
rel ans[MAXN],rec[MAXN];
int n;

void init(){
    for(int i=0;i<MAXN;i++){
        father[i] = i;
        mark[i] = 0;
    }
    memset(ans,0,sizeof(ans));
    memset(rec,0,sizeof(rec));
}

int  Find(int u){
    return u==father[u]?u:Find(father[u]);
}

void Union(int u,int v){
    father[u] = Find(u);
    father[v] = Find(v);
    if(father[u]>father[v])father[father[u]] = father[v];
    else father[father[v]] = father[u];
}

bool cmp(const rel &a,const rel &b){
    if(a.pers!=b.pers)
        return a.pers>b.pers;
    return a.minid<b.minid;
}

int main()
{
    while(scanf("%d",&n)!=EOF){
        init();
       // cout<<Find(8888)<<endl;
        for(int i=0;i<n;i++){
            scanf("%d%d%d",&a[i].npcid,&a[i].faid,&a[i].maid);
            mark[a[i].npcid] = 1;
            if(a[i].faid!=-1){
                Union(a[i].npcid,a[i].faid);
                mark[a[i].faid] = 1;
            }
            if(a[i].maid!=-1){
                Union(a[i].npcid,a[i].maid);
                mark[a[i].maid] = 1;
            }
            scanf("%d",&a[i].k);
            for(int j=0;j<a[i].k;j++){
                scanf("%d",&a[i].sid[j]);
                if(a[i].sid[j]!=-1){
                    Union(a[i].npcid,a[i].sid[j]);
                    mark[a[i].sid[j]] = 1;
                }
            }
            scanf("%d%d",&a[i].n,&a[i].s);
        }
        int fa;
        for(int i=0;i<n;i++){
            fa = Find(a[i].npcid);
            ans[fa].minid = fa;
            ans[fa].n += a[i].n;
            ans[fa].s += a[i].s;
        }
        for(int i=0;i<MAXN;i++){
            if(mark[i]){
                fa = Find(i);
                ans[fa].tol ++;
            }
        }
        int top = 0;
        for(int i=0;i<MAXN;i++){
            if(ans[i].tol){
                rec[top] = ans[i];
                rec[top].pern = rec[top].n*1.0/rec[top].tol;
                rec[top].pers = rec[top].s*1.0/rec[top].tol;
                top++;
            }
        }
        sort(rec,rec+top,cmp);
        cout<<top<<endl;
        for(int i=0;i<top;i++){
            if(rec[i].minid<10){
                cout<<"000";
            }else if(rec[i].minid<100){
                cout<<"00";
            }else if(rec[i].minid<1000){
                cout<<"0";
            }
            printf("%d %d %.3lf %.3lf
",rec[i].minid,rec[i].tol,rec[i].pern,rec[i].pers);
        }
    }
    return 0;
}
并查集

L2-4. 最长对称子串

注意连续子串

#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <cctype>
#include <cmath>
#include <stack>
#include <string>
#include <queue>
#include <vector>
#include <map>
#include <algorithm>

const int inf = 0x3f3f3f;
const int MAXN = 1e3+10;

using namespace std;

string ts1,ts2;
int dp[2][MAXN];

int main()
{
    while(getline(cin,ts1)){
       // transform(ts1.begin(),ts1.end(),ts1.begin(),::tolower);
        int len = ts1.size();
        ts2 = ts1;
        reverse(ts2.begin(),ts2.end());
       // cout<<ts2<<endl;
        int mmax = 0;
        memset(dp,0,sizeof(dp));
        for(int i=1;i<=len;i++){
            for(int j=1;j<=len;j++){
                if(ts1[i-1]==ts2[j-1]){
                    dp[i%2][j] = dp[(i-1)%2][j-1]+1;
                    mmax = max(mmax,dp[i%2][j]);
                }
                else
                    dp[i%2][j] = 0;
            }
        }
        cout<<mmax<<endl;
    }
    //cout << "Hello world!" << endl;
    return 0;
}
连续lcs

L3-1. 肿瘤诊断

三维bfs

#include <iostream>
#include <cstdlib>
#include <cstdio>
#include <cstring>
#include <cmath>
#include <stack>
#include <string>
#include <queue>
#include <map>
#include <set>
#include <algorithm>

const int inf = 0x3f3f3f;
const int X = 1286;
const int Y = 128;
const int Z = 60;

using namespace std;
struct ip{
    int x;
    int y;
    int z;
};

int mov[6][3]={{0,0,1},{0,0,-1},{0,1,0},{0,-1,0},{1,0,0},{-1,0,0}};
int G[Z][X][Y];
stack<ip>S;
queue<ip>Q;
int x,y,z,t;

int check(int nx,int ny,int nz){
    if(nx<0||nx>=x||ny<0||ny>=y||nz<0||nz>=z||!G[nz][nx][ny])return 0;
    return 1;
}

int main()
{
    while(scanf("%d%d%d%d",&x,&y,&z,&t)!=EOF){
        ip tmp;
        for(int i=0;i<z;i++){
            for(int j=0;j<x;j++){
                for(int k=0;k<y;k++){
                    scanf("%d",&G[i][j][k]);
                    if(G[i][j][k]){
                        tmp.z = i;
                        tmp.x = j;
                        tmp.y = k;
                        S.push(tmp);
                    }
                }
            }
        }
        ip tf;
        int cnt,sum=0;
        while(!S.empty()){
            tf = S.top();
            S.pop();
            cnt = 0;

            if(G[tf.z][tf.x][tf.y]){
                cnt = 1;
                G[tf.z][tf.x][tf.y] = 0;
                Q.push(tf);
                while(!Q.empty()){
                    tf = Q.front();
                    Q.pop();
                    int nx,ny,nz;
                    for(int i=0;i<6;i++){
                        nx = tf.x+mov[i][0];
                        ny = tf.y+mov[i][1];
                        nz = tf.z+mov[i][2];
                        if(check(nx,ny,nz)){
                            tmp.x = nx;
                            tmp.y = ny;
                            tmp.z = nz;
                            Q.push(tmp);
                            cnt++;
                            G[nz][nx][ny] = 0;
                        }
                    }
                }
            }

            //cout<<cnt<<endl;
            if(cnt>=t)sum+=cnt;
        }
        cout<<sum<<endl;
    }
    //cout << "Hello world!" << endl;
    return 0;
}
stack+queue模拟

L3-001. 凑零钱

背包,达到背包容量,货物越多,每个货物的val越小,同理,零钱越多,也就越散,还有注意同样数量的的货物,存在val大的货物越多,也就会有越小可能的val货物,这样才能满足字典序输出的要求

dp[i] = max(dp[i-val]+1,dp[i])

#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <cmath>
#include <stack>
#include <string>
#include <queue>
#include <vector>
#include <map>
#include <algorithm>

const int inf = 0x3f3f3f;
const int MAXN = 1e2+10;
const int MAXM = 1e4+10;

using namespace std;

int dp[MAXN];
int ans[MAXN];
int a[MAXM];

void print(int u){
    if(u==ans[u]){
        cout<<u;
        //cout<<"haha"<<endl;
        return ;
    }
    print(u-ans[u]);
    cout<<" "<<ans[u];
}

int main()
{
    int n,m;
    while(scanf("%d%d",&n,&m)!=EOF){
        memset(dp,0,sizeof(dp));
        memset(ans,0,sizeof(ans));
        for(int i=1;i<=n;i++)
            scanf("%d",&a[i]);
        sort(a+1,a+n+1);

        for(int i=1;i<=n;i++){
            for(int j=m;j>=a[i];j--){
                if(dp[j-a[i]]||j==a[i]){
                    if(dp[j]<=dp[j-a[i]]+1){
                        dp[j] = dp[j-a[i]]+1;
                        ans[j] = a[i];
                    }
                }
            }
        }

       /* for(int i=1;i<=m;i++){
            cout<<ans[i]<<" ";
        }
        cout<<"debug"<<endl;*/
       // cout<<"debug"<<endl;
        if(!ans[m]){
            cout<<"No Solution"<<endl;
            continue;
        }
        print(m);
        cout<<endl;
    }
    //cout << "Hello world!" << endl;
    return 0;
}
01背包

L3-003. 社交集群

还是裸并查集的题目,题目看错,wa了一次

#include <iostream>
#include <cstdlib>
#include <cstdio>
#include <cmath>
#include <cstring>
#include <stack>
#include <string>
#include <queue>
#include <vector>
#include <map>
#include <set>
#include <algorithm>

const int inf = 0x3f3f3f;
const int MAXN = 1e3+10;

using namespace std;

int father[MAXN];
int mark[MAXN];
int ans[MAXN],rec[MAXN];
int n,m;

void init(){
    for(int i=0;i<MAXN;i++)
        father[i] = i;
    memset(ans,0,sizeof(ans));
    memset(rec,0,sizeof(rec));
    memset(mark,0,sizeof(mark));
}

int Find(int u){
    return u==father[u]?u:Find(father[u]);
}

void Union(int u,int v){
    father[u] = Find(u);
    father[v] = Find(v);
    father[father[u]] = father[v];
}

bool cmp(const int &a,const int &b){
    return a>b;
}

int main()
{
    while(scanf("%d",&n)!=EOF){
        init();
        int v;
        for(int i=0;i<n;i++){
            scanf("%d:",&m);
            for(int j=0;j<m;j++){
                scanf("%d",&v);
                if(!mark[v]){
                    mark[v] = i+1;
                }else{
                    Union(i+1,mark[v]);
                }
            }
        }

        int fa;
        for(int i=1;i<=n;i++){
            fa = Find(i);
          // cout<<fa<<endl;
           // cout<<"debug"<<endl;
            ans[fa]++;
        }
        int top=0;
        for(int i=1;i<=n;i++){
            if(ans[i])
                rec[top++] = ans[i];
        }
        cout<<top<<endl;
        sort(rec,rec+top,cmp);
        cout<<rec[0];
        for(int i=1;i<top;i++)
            cout<<" "<<rec[i];
        cout<<endl;
    }
    //cout << "Hello world!" << endl;
    return 0;
}
并查集
在一个谎言的国度,沉默就是英雄
原文地址:https://www.cnblogs.com/EdsonLin/p/5496700.html