2019 WFU Summer training (一)

1.vector

题目:https://vjudge.net/contest/310193#problem/A

代码:

#include<cstdio>
#include<string>
#include<vector>
#include<iostream>
using namespace std;
const int maxn = 30;
int n;
vector<int> pile[maxn];
//查找木块a所在的pile和height
void find_block(int a,int& p,int & h)
{
    for (p = 0; p < n; p++)
    {
        for ( h = 0; h < pile[p].size(); h++)
        {
            if (pile[p][h]==a)
            {
                return;
            }
        }
 
    }
}
//把第p堆高度为h的木块上方的所有木块放回原位
void clearAbove(int p,int h)
{
    for (size_t i = h+1; i < pile[p].size(); i++)
    {
        int b = pile[p][i];
        pile[b].push_back(b);//把木块b放回原位
 
    }
    pile[p].resize(h + 1);//只保留第0-h元素
}
//把第p堆高度为h及以上的移动到p2顶部
void pileonto(int p,int h,int p2)
{
    for (size_t i = h; i < pile[p].size(); i++)
    {
        pile[p2].push_back(pile[p][i]);
    }
    pile[p].resize(h);
}
//输出
void print()
{
    for (size_t i = 0; i < n; i++)
    {
        printf_s("%d", i);
        for (size_t j = 0; j < pile[i].size(); j++)
        {
            printf_s(" %d", pile[i][j]);
        }
        printf_s("\n");
 
    }
}
 
int main()
{
    int a, b;
    cin >> n;
    string s1, s2;
    for (size_t i = 0; i < n; i++)
    {
        pile[i].push_back(i);
    }
    while (cin>>s1>>a>>s2>>b)
    {
        int pa, pb, ha, hb;
        find_block(a,pa, ha);
        find_block(b, pb, hb);
        if (pa == pb) continue;
        if (s2 == "onto") clearAbove(pb, hb);
        if (s1 == "move") clearAbove(pa, ha);
        pileonto(pa, ha, pb);
    }
    print();
    return 0;
}

数据结构核心vector<int> pile[maxn]

每一个木块堆的高度不确定,所以用vector来保存比较合适,而木块堆的个数不超过n,所以用一个数组来存储就可以。

2.set

题目:https://vjudge.net/contest/310193#problem/B

代码:

#include<iostream>  
#include<string>  
#include<set>  
#include<sstream>  
using namespace std;  
  
set<string> dict;    //为字典设置一个名为dict-short的集合,它基于字符串类型;  
  
int main(){  
    string s,buf; 
    
    while (cin>>s){  
        for (int i=0;i<s.length();i++)  
          if (isalpha(s[i]))       //isalpha函数:判断字符ch是否为英文字母,若为英文字母,返回非0.若不是字母,返回0
              s[i]=tolower(s[i]);    //如果它是一个字母,把它变成小写。 
          else 
              s[i]=' ';  
        stringstream ss(s);      //如果是空格,忽略它
        while (ss>>buf) 
            dict.insert(buf);   //插入到已经是有序的集合,
    }  
    for (set<string>::iterator it=dict.begin();it!=dict.end();++it)//迭代器就像一个点,从头到尾扫描它并输出
      cout<<*it<<endl;          
    
    
    return 0;  
}

set是数学上的集合,它是一个不包含重复元素的集合,并且自动重小到大排序。输入时把所有非字母的字符变成空格,然后利用stringstream得到各个单词。

3.map

题目:https://vjudge.net/contest/310193#problem/C

代码:

#include <iostream>
#include <string>
#include <vector>
#include <map>
#include <algorithm>
#include <cstring>
 
using namespace std;
 
vector<string> v;
map<string,int> q;
 
int main()
{
    string s;
    while(cin >> s)
    {
        if(s == "#")
            break;
        else
        {
            v.push_back(s);
 
            int l = s.size();
            for(int i = 0; i < l; i++)
            {
                if(s[i] >= 65 && s[i] <= 90)
                {
                    s[i] += 32;
                }
            }
            sort(s.begin(),s.end());
            q[s]++;
        }
    }
 
    int n = v.size();
    sort(v.begin(),v.end());
    string t;
    for(int i = 0;i < n; i++)
    {
        t = v[i];
        int len = t.size();
        for(int i = 0; i < len; i++)
        {
            if(t[i] >= 65 && t[i] <= 90)
            {
                t[i] += 32;
            }
        }
        sort(t.begin(),t.end());
        if(q[t]==1)
            cout << v[i] << endl;
 
    }
    return 0;
}

就是查找字母重组后出现一次的单词;先将单词变为小写并按字典序排列,用map容器存储单词,然后用其映射表示出现其次数。最后将出现一次的单词保存到set中,将其输出。

4.queue的使用

题目:https://vjudge.net/contest/310193#problem/D

代码:

#include<bits/stdc++.h>
#include<queue>
#include<map>
using  namespace std;
const int maxn=1000+10;
int main(){
    int t,cnt=0;
    while(scanf("%d",&t)==1&&t){
        printf("Scenario #%d\n",++cnt);
        map<int,int>team;
        for(int i=0;i<t;i++){
            int n,x;
            scanf("%d",&n);
            while(n--){
                cin>>x;
                team[x]=i;
            }
        } 
        queue<int>q,q2[maxn];
        for(;;){
            int x;
            char cmd[10];
            scanf("%s",cmd);
            if(cmd[0]=='S') break;
            else if(cmd[0]=='D'){
                int t=q.front();
                printf("%d\n",q2[t].front());
                q2[t].pop();
                if(q2[t].empty()) q.pop();
            }
            else if(cmd[0]=='E'){
                scanf("%d",&x);
                int t=team[x];
                if(q2[t].empty()) q.push(t);
                q2[t].push(x);
            }
        }
        printf("\n");
    }
    return 0;
}

用到两个队列,一个是每个团队自己是一个队列,而每个团队整体之间又构成一个队列。

5.优先队列的使用

题目:https://vjudge.net/contest/310193#problem/E

代码:

#include<bits/stdc++.h>
#include<queue>
#include<vector>
#include<set>
using namespace std;
typedef long long ll;
priority_queue<int,vector<ll>,greater<ll> >pq;
set<ll>s; 
const int coo[3]={2,3,5};
int main(){
    pq.push(1);
    s.insert(1);
    for(int i=1;;i++){
        ll x=pq.top();
        pq.pop();
        if(i==1500){
            cout<<"The 1500'th ugly number is "<<x<<".\n";
            break;
        }
        for(int j=0;j<3;j++){
            ll x2=x*coo[j];
            if(!s.count(x2)){
                s.insert(x2);
                pq.push(x2);
            }
        }
    }
    return 0;
}

丑数的2,3,5倍仍然是丑数(排除重复的)

6.全排列函数

题目:https://vjudge.net/contest/310193#problem/F

代码:

#include<iostream>
#include<algorithm>
#include<cstring>
using namespace std;
const int maxn=10010;
int num[maxn];
int main()
{
    int n,m;
    while(cin>>n>>m){
        int cnt=1;
        memset(num,0,sizeof(num));
        for(int i=0;i<n;i++){
            num[i]=i+1;
        }
        while(true){
            if(cnt==m){
                cout<<num[0];
                for(int i=1;i<n;i++){
                    cout<<" "<<num[i];
                }
                cout<<"\n";
                break;
            }
            next_permutation(num,num+n);
            cnt++;
        }
    }    
    return 0;
}

emmm……next_permutation(num,num+n)函数的用法考察

7.拓扑排序

题目:https://vjudge.net/contest/310193#problem/G

代码:

#include<cstdio>
#include<cstring>
#include<queue>
#include<iostream>
using namespace std;
int ans[510][510];
int n,indegree[510];
queue<int>q;
void topsort()
{
    int i,j,t,top;
    queue<int>q;
    for(i=1;i<=n;++i)
    {
        if(indegree[i]==0)
        {
            q.push(i);
            break;
        }    
    }
    int sign=1;
    while(!q.empty())
    {
        top=q.front();
        q.pop();
        indegree[top]=-1;
        if(sign)
        {
            printf("%d",top);
            sign=0;
        }
        else   
            printf(" %d",top);
        for(i=1;i<=n;++i)//注意,以当前第一名为前驱的点的前驱数量都要减少 
        {
            if(ans[top][i]==1)
               indegree[i]--;
        }
        for(i=1;i<=n;++i)
        {
            if(indegree[i]==0)
            {
                q.push(i);
                break;
            }
        }
    }
    printf("\n");
} 
int main()
{
    int i,m,u,v;
    while(cin>>n>>m){
        memset(indegree,0,sizeof(indegree));
        memset(ans,0,sizeof(ans));
        while(m--){
            cin>>u>>v;
            if(ans[u][v]==0){
                ans[u][v]=1;
                indegree[v]++;
            }
        }
        topsort();
    }
    return 0;
}

将输入的数据存到图中,同时更新入度的数组。在拓扑排序时,首先找到入度为0 的点,接着遍历所有的点,看是不是这个入度为0 的点的邻接点。如果是,那么入度-1。字典序的控制依赖于刚开始的循环。并且,在没有入度为0的仍然按照字典序存入res数组。

8.拓扑排序2

题目:https://vjudge.net/contest/310193#problem/H

代码:

#include<iostream>
#include<vector>
#include<queue>
using namespace std;
const int maxn=1e5+10;
vector<int>vec[maxn];
queue<int>q;
int indeg[maxn];
int n,m;
bool topsort(){
    int num=0;
    while(!q.empty()) q.pop();
    for(int i=0;i<n;i++){
        if(!indeg[i]) q.push(i);
    }
    while(!q.empty()){
        int now=q.front();
        q.pop();
        num++;
        for(int i=0;i<vec[now].size();i++){
            if(--indeg[vec[now][i]]==0){
                q.push(vec[now][i]);
            }
        }
    }
    if(num==n)return true;
    return false;
}
int main(){
    while(true){
        cin>>n>>m;
        if(n==0) break;
        for(int i=0;i<n;i++){//清空 
            vec[i].clear();
            indeg[i]=0;
        }
        memset(indeg,0,sizeof(indeg));
        while(m--){
            int u,v;
            cin>>u>>v;
            vec[u].push_back(v);
            indeg[v]++;
        }
        if(topsort()){
            puts("YES");
        }
        else
            puts("NO");
    }
    return 0;
}

思路同一

9,10并查集水题(改下输入输出)

模板:

#include <cstdio>
#include <cstring>
#include <algorithm>
#include <iostream>
using namespace std;
const int maxn = 30005;
int f[maxn], rank[maxn];//f[]是根节点,rank[]是 根节点的高度 
int find_root(int x)  //查找根节点 
{
    if(x != f[x])
        f[x] = find_root(f[x]);
    return f[x];
} 
int main()
{
    int n,m,k;
    while(cin>>n>>m)
    {
        if(n==0&&m==0) break;
        int a, b;
        for(int i = 0; i < n; i++)
        {
            f[i] = i;
            rank[i] = 0;
        }
        if(m == 0)
        {
            printf("1\n");
            continue;
        }
        while(m--)        //输入各个集合 
        {
            cin>>k;
            k--;
            cin>>a;
            while(k--)
            {
                cin>>b;
                a = find_root(a);
                b = find_root(b);
                if(rank[a]>rank[b]){    //高度更高的为根节点 
                    f[b] = a;
                }
                else{
                    f[a] = b;
                    if(rank[a] == rank[b])    rank[b]++;
                }
                a = b;
            }
        }
        int ans = 0, x = find_root(0);
        for(int i=0; i<n; i++)
        {
            if(find_root(i) == x) ans++;  //这里不能写f[i]==x,会出错,要再更新一次根节点才行 
        }
        printf("%d\n", ans);
    }
    return 0;
}

11.反向拓扑

#include<algorithm>
#include<iostream>
#include<cstring>
#include<vector>
#include<queue>
using namespace std;
const int maxn=10005;
queue<int>q;
vector<int>vec[maxn];
int indeg[maxn],array[maxn];
int n,m;
int topsort(){
    while(!q.empty()) q.pop();
    for(int i=1;i<=n;i++){
        if(!indeg[i]) {
            q.push(i);
        }
    }
    int num=0;
    while(!q.empty()){
        int now=q.front();
        q.pop();
        num++;
        for(int i=0;i<vec[now].size();i++){
            if(--indeg[vec[now][i]]==0){
                q.push(vec[now][i]);
                array[vec[now][i]]=max(array[now]+1,array[vec[now][i]]);
            }
        }
    }
    if(num!=n)
    return -1;
    int sum=0;
    for(int i=1;i<=n;i++)
    sum+=array[i]+888;
    return sum;
}
int main(){
    while(cin>>n>>m){
        memset(vec,0,sizeof(vec));
        memset(indeg,0,sizeof(indeg));
        memset(array,0,sizeof(array));
        while(m--){
            int u,v;
            cin>>u>>v;
            vec[v].push_back(u);
            indeg[u]++;
        }
        cout<<topsort()<<endl;
    }
    return 0;
}

猜你喜欢

转载自www.cnblogs.com/BYBL/p/11222124.html