zoukankan      html  css  js  c++  java
  • 每天一套题打卡|河南省第八届ACM/ICPC

    A 挑战密室

    化学方程式求分子量
    这题我懒得写了

    可以用map<string,int>哈希表,表示每种分子的相对分子质量
    之后,从头遍历到尾。
    1.数字:连读直到不是数字
    2.字母:连读直到不是字母
    3.括号:从左括号开始遍历,重复1、2,到右括号退出

    下面这个代码可以AC,但是有bug的,数字超过10,或者字母连着>3个就挂了

    #include<cstdio>
    #include<cstring>
    #include<map>
    #include<string>
    using namespace std; 
    map<string,int> x;
    int main()
    {
    	x["N"]=14;x["C"]=12;x["O"]=16;x["Cl"]=35;x["S"]=32;x["H"]=2;x["Al"]=27;x["Ca"]=40;x["Zn"]=65;x["Na"]=23;
        int t;scanf("%d",&t);
        char ch[52],xx[3];
        while (t--)
        {
        	int i;
        	scanf("%s",ch);int ll=strlen(ch);
        	for (i=0;i<ll;i++)
        	if (ch[i]=='=')
        	break;
        	int lplp=1;
        	i++;int s,ss=0,ks;
        	if ('0'<ch[i]&&ch[i]<='9')
    		{
    			lplp=ch[i]-'0';
    		    i++;
    	    }
        	for (;i<ll;i++)
        	{
        		if (ch[i]=='+')
        		break;
        		if (ch[i]=='(')
        		{
        			s=0;i++;
        			for (;;i++)
        			{
        				if (ch[i]==')') break;
        				if ('A'<=ch[i]&&ch[i]<='Z')
        				{
        					xx[0]=ch[i];
        					xx[1]=0;
        					if ('a'<=ch[i+1]&&ch[i+1]<='z')
        					{
        						i++;
        						xx[1]=ch[i];
        						xx[2]=0;
        					}
        				}
        				ks=x[xx];
        				if ('0'<ch[i+1]&&ch[i+1]<='9')
        		    	{
        		    		i++;
        			    	ks*=ch[i]-'0';
        			    }
        			    s+=ks;
        			}
        			if ('0'<ch[i+1]&&ch[i+1]<='9')
        			{
        				i++;
        				s*=ch[i]-'0';
        			}
        			ss+=s;
        		}
        		else
        		{
        			if ('A'<=ch[i]&&ch[i]<='Z')
    				{
    					xx[0]=ch[i];
    					xx[1]=0;
    					if ('a'<=ch[i+1]&&ch[i+1]<='z')
    					{
    						i++;
    						xx[1]=ch[i];
    						xx[2]=0;
    					}
    				}
    				ks=x[xx];
    				if ('0'<ch[i+1]&&ch[i+1]<='9')
    		    	{
    		    		i++;
    			    	ks*=ch[i]-'0';
    			    }
    			    ss+=ks;
        		}
        	}
        	ss*=lplp;
        	printf("%04d
    ",ss);
        }
    	return 0;
    }
    
    

    B 最大岛屿

    dfs统计连通分量模板

    void dfs(int x,int y){
    	flood[x][y] = area;
    	for(int i=0;i<8;i++){
    		int tx = x + dr[i][0];
    		int ty = y + dr[i][1];
    		if(in(tx,ty) && a[tx][ty] == 1 && flood[tx][ty] == 0){
    			dfs(tx,ty);
    		}
    	}
    }
    

    主要注意地图的读写,中间有空格,可以用getchar读取

    #include<bits/stdc++.h>
    using namespace std;
    
    const int maxn = 510;
    int m,n,t;
    int a[maxn][maxn];
    int area = 0;
    int flood[maxn][maxn];
    int dr[8][2] = {{0,1},{0,-1},{-1,0},{1,0},{1,-1},{-1,1},{-1,-1},{1,1}};
    int s[maxn*maxn];
    
    bool in(int x,int y){
    	return x>=1 && x<=n && y>=1 && y<=m;
    }
    
    void dfs(int x,int y){
    	flood[x][y] = area;
    	for(int i=0;i<8;i++){
    		int tx = x + dr[i][0];
    		int ty = y + dr[i][1];
    		if(in(tx,ty) && a[tx][ty] == 1 && flood[tx][ty] == 0){
    			dfs(tx,ty);
    		}
    	}
    }
    
    int main(){
    	cin>>n>>m>>t;
    	getchar();
    	char ch;
    	for(int i=1;i<=n;i++){
    		for(int j=1;j<=m;j++){
    			while((ch = getchar()) == ' '){}
    			a[i][j] = ch - '0';
    		}
    		getchar();
    	}
    	for(int i=1;i<=n;i++){
    		for(int j=1;j<=m;j++){
    			if(flood[i][j] == 0 && a[i][j] == 1){
    				area++;
    				dfs(i,j);
    			}
    		}
    	}
    	for(int i=1;i<=n;i++){
    		for(int j=1;j<=m;j++){
    			if(flood[i][j] != 0){
    				s[flood[i][j]]++;
    			}
    		}
    	}
    	long long maxarea = 0;
    	for(int i=1;i<=area;i++){
    		if(s[i] > maxarea) maxarea = s[i];
    	}
    	cout<<area<<" "<<maxarea*t<<endl;
    	return 0;
    } 
    

    C 最少换乘

    写bfs搜索(求最短路)过的
    首先把所有与起点1同一路线的点都入队(step表示换成次数 = 0)
    bfs每次取出头部,搜索
    当两点时同一公交路线时,新状态step不变
    当两点不是同一公交路线时,新状态step+1

    vis二维数组标记这条边是否走过

    另外注意:这道题读入比较麻烦
    没有告诉我们 每行有多少个数

    我用getline函数来读的,getline(std::cin,string),读入到字符串string中

    其他博客写的题解,用单源点最短路dijkstra做的 https://blog.csdn.net/dreamlandz/article/details/51509382

    #include<bits/stdc++.h>
    using namespace std;
    
    
    const int maxn = 510;
    int g[maxn][maxn];
    int t;
    int n,m;
    int a[maxn];
    int vis[maxn][maxn];
    struct edge{
    	int u;
    	int w;
    	edge(int uu = 0,int ww = 0){
    		u = uu;
    		w = ww;
    	}
    };
    vector<edge> v[maxn];
    int sstation;
    int estation;
    struct node{
    	int xx;
    	int station;
    	int step;
    	node(int xxx,int stations,int steps){
    		xx = xxx;
    		station = stations;
    		step = steps;
    	}
    };
    
    int bfs(){
    	queue<node> q;
    //	q.push(node(1,3,0)); //这里应该把和a相连的全部入队 就是下面几行 
    	for(int i=0;i<v[1].size();i++){
    		vis[1][v[1][i].u]= 1;
    		q.push(node(v[1][i].u,v[1][i].w,0));
    	}
    	int ans = 0x3f3f3f3f;
    	while(!q.empty()){
    		int x = q.front().xx;
    		int sta = q.front().station;
    		int step = q.front().step;
    		if(x==n){
    			ans = min(ans,step);
    		}
    		q.pop();
    		for(int i=0;i<v[x].size();i++){
    			if(vis[x][v[x][i].u]) continue;
    			if(v[x][i].w == sta){
    				vis[x][v[x][i].u] = 1;
    				q.push(node(v[x][i].u,sta,step));
    			}else{
    				vis[x][v[x][i].u] = 1;
    				q.push(node(v[x][i].u,v[x][i].w,step+1));
    			}
    		}
    	}
    	return ans;
    }
    
    
    int main(){
    	cin>>t;
    	while(t--){
    		memset(vis,0,sizeof(vis));
    		cin>>m>>n;
    		getchar();
    		for(int i=1;i<=m;i++){
    			string temp;
    			getline(std::cin, temp);
    			int len = 0;
    			for(int j=0;j<temp.length();j++){
    				int sum = 0;
    				while(j < temp.length() && temp[j] != ' '){
    					sum = sum*10 + (temp[j] - '0');
    					j++;
    				}
    				a[len++] = sum;
    			}
    			for(int j=0;j<len;j++){
    				for(int p = j+1;p<len;p++){
    					v[a[j]].push_back(edge(a[p],i));
    				}
    			}
    		}
    		int ans = 0;
    		ans = bfs();
    		if(ans == 0x3f3f3f3f){
    			cout<<"NO"<<endl;
    		}else{
    			cout<<ans<<endl;
    		}
    		for(int i=0;i<maxn-1;i++){
    			v[i].clear();
    		} 
    	}
    	return 0;
    } 
    

    D 引水工程

    最小生成树,prim和kru...都可以过

    kru最小生成树
    建图时 自己对自己也算一条边(如果要选条边,不能算n-1条边里)

    #include<bits/stdc++.h>
    using namespace std;
    
    /*
    想法1: 
    	kru最小生成树
    	建图时 自己对自己也算一条边(如果要选条边,不能算n-1条边里)
    */
    
    /*
    想法2:从权值最小的开始建水库 prim算法 
    */
    
    
    //kru做法
    int n,m,minn,father[305],sum,tem[305];
    struct node
    {
        int x,y,l;
    }a[90005];
    
    bool cmp(node a,node b)
    {
        return a.l<b.l;
    }
    
    int find(int x)                      //  做了时间上的优化 ,但是 在空间复杂度上比较高
    {
        if(x!=father[x])
            father[x]=find(father[x]);
        sum++;
        return father[x];
    }
    
    bool merge(int x,int y)    // 做了时间复杂度上的优化  让并查集的 深度尽量  浅
    {
        int sum1,sum2;
        sum=0;
        x=find(x);
        sum1=sum;        //    x  的深度
        sum=0;
        y=find(y);
        sum2=sum;       //    y   的深度
        if(x!=y)
        {
            if(sum1>sum2)
                father[y]=x;
            else
                father[x]=y;
            return true;
        }
        else
            return false;
    }
    int main()              //  先用  Dijkstra 做一次   // Dijkstra 是 根据边来做的
    {
        int t;
        scanf("%d",&t);
        while(t--)
        {
            scanf("%d",&n);
            for(int i=0;i<=n;i++)
                father[i]=i;
            int q=0;
            //i从0开始 多输了一次 
            for(int i=0;i<=n;i++)
            {
                for(int j=1;j<=n;j++)
                {
                    int e;
                    scanf("%d",&e);
                    a[q].x=j;
                    a[q].y=i;
                    a[q].l=e;
                    q++;
                }
            }
            int sum3=0,count1=0;
            sort(a,a+q,cmp);
            for(int i=0;i<q;i++)
            {
                if(merge(a[i].x,a[i].y))
                {
                    sum3+=a[i].l;
                    count1++;
                }
                if(count1==n) // 如果边数等于 所有需要连接的 点数-1的话 就跳出去
                    break;
            }
            printf("%d
    ",sum3);
        }
        return 0;
    }
    

    Prim求最小生成树
    在选择最小邻接边时,和顶点再比较一下

    #include<bits/stdc++.h>
    using namespace std;
    
    
    const int inf = 0x3f3f3f3f;
    const int maxn = 510;
    bool vis[maxn];
    int dist[maxn];
    int g[maxn][maxn];
    int a[maxn];
    int n,t;
    
    //想法2:从权值最小的开始建水库 prim算法
    //有水可以自身引水 或者其它地区引水 所以如果 最小的邻接边的费用 比对应顶点的权值大 就自己引水
    
    int Prim(int pos){
    	int ans = 0;
    	memset(vis,false,sizeof(vis));
    	ans = a[pos];
    	vis[pos] = true;
    	for(int i=1;i<=n;i++) dist[i] = g[pos][i];
    	for(int i=1;i<=n-1;i++){
    		int minc = inf;
    		int p = -1;
    		for(int j=1;j<=n;j++){
    			if(!vis[j] && minc > dist[j]){
    				minc = dist[j];
    				p = j;
    			}
    		}
    		//应题目中的要求(每个点都要有水)
    		//有水可以自身引水 或者其它地区引水 所以如果 最小的邻接边的费用 比对应顶点的权值大 就自己引水 
    		if(minc > a[p]){
    			ans += a[p];
    			vis[p] = true;
    			continue;
    		}
    		
    		vis[p] = true;
    		ans += dist[p];
    		for(int j=1;j<=n;j++){
    			if(!vis[j] && dist[j] > g[p][j]){
    				dist[j] = g[p][j];
    			}
    		}
    	}
    	return ans;
    }
    
    int main(){
    	cin>>t;
    	while(t--){
    		cin>>n;
    		int minv = inf;
    		int pos = 1;
    		for(int i=1;i<=n;i++){
    			cin>>a[i];
    			if(a[i] < minv){
    				minv = a[i];
    				pos = i;
    			}
    		}
    
    		for(int i=1;i<=n;i++){
    			for(int j=1;j<=n;j++){
    				cin>>g[i][j];
    			}
    		}
    		cout<<Prim(pos)<<endl;
    	}
    	return 0;
    }
    

    F Distribution

    校赛也出了这一道题,比较简单
    给定两条线,求一三象限 与 二四象限 上的 点数差

    #include<bits/stdc++.h>
    using namespace std;
    
    const int maxn = 1100;
    int n,m;
    int g[maxn][maxn]; // 0开始(0也算)
    int maxx = 0;
    int maxy = 0;
    
    int solve(int x,int y){
    	int sum = 0;
    	for(int i=0;i<x;i++){
    		for(int j=0;j<y;j++){
    			if(g[i][j] == 1) 
    				sum++;
    		}
    	}
    	for(int i=x+1;i<=maxx+1;i++){
    		for(int j=y+1;j<=maxy+1;j++){
    			if(g[i][j] == 1) 
    				sum++;
    		}
    	}
    	return sum;
    }
    
    int main(){
    	cin>>n>>m;
    	for(int i=1;i<=n;i++){
    		int xi,yi;
    		cin>>xi>>yi;
    		g[xi][yi] = 1;
    		if(xi > maxx) maxx = xi;
    		if(yi > maxy) maxy = yi;
    	}
    	for(int i=1;i<=m;i++){
    		int x,y;
    		cin>>x>>y;
    		int ans1 = 0;
    		int ans2 = 0;
    		ans1 = solve(x,y);
    		ans2 = n - ans1;
    		cout<<ans1 - ans2<<endl;
    	}
    	return 0;
    } 
    

    G Interference Signal

    题意:给定n个数,求最大的 至少连续m个数的平均值
    枚举起点,算平均值就可以了

    #include<bits/stdc++.h>
    using namespace std;
    
    const int maxn = 2050;
    int t;
    int a[maxn];
    int sum[maxn];
    int n,m;
    
    int main(){
    	cin>>t;
    	while(t--){
    		cin>>n>>m;
    		for(int i=1;i<=n;i++){
    			cin>>a[i];
    			a[i] = a[i] * 1000;
    		}
    		memset(sum,0,sizeof(sum));
    		sum[0] = 0;
    		for(int i=1;i<=n;i++){
    			sum[i] = sum[i-1] + a[i];
    		}
    		double average = 0;
    		for(int i=1;i<=n;i++){
    			for(int j=i+m-1;j<=n;j++){
    				double avetemp = (sum[j] - sum[i-1])*1.0/ (j-i+1);
    				if(avetemp > average) average = avetemp;
    			}
    		}
    		int ans = average;
    		printf("%d
    ",ans);
    	}
    	return 0;
    } 
    
  • 相关阅读:
    暑期集训第五天(6-26)题解及总结
    暑期集训第四天(6-25)题解及总结
    暑期集训第三天(6-24)题解及总结
    暑期集训第二天(6-23)题解及总结
    暑期集训第一天(6-22)题解及总结(于6-23补)
    51nod1534 棋子游戏
    CF938D Buy a Ticket
    P4588 [TJOI2018]数学计算
    yumdownloader:下载保存Yum包而不安装
    RHEL 7.4 下yum安装配置nginx与php
  • 原文地址:https://www.cnblogs.com/fisherss/p/10800693.html
Copyright © 2011-2022 走看看