WEEK2周记 A题———模拟类

WEEK2周记 A题———模拟类

一、题意

  • 1.简述

    在这里插入图片描述
    假设如上图,这个烷烃基有6个原子和5个化学键,6个原子分别标号1~6,然后用一对数字 a,b 表示原子a和原子b间有一个化学键。这样通过5行a,b可以描述一个烷烃基。你的任务是甄别烷烃基的类别。
    原子没有编号方法,比如
    1 2
    2 3
    3 4
    4 5
    5 6

    1 3
    2 3
    2 4
    4 5
    5 6
    是同一种,本质上就是一条链,编号其实是没有关系的,可以在纸上画画就懂了。
  • 2.输入格式

    输入第一行:数据的组数T(1≤T≤200000)。每组数据有5行,每行是两个整数a, b(1≤a,b≤6,a ≤b)。数据保证,输入的烷烃基是以上5种之一。
  • 3.输出格式

    每组数据,输出一行,代表烷烃基的英文名。
  • 4.样例

    Input
    2
    1 2
    2 3
    3 4
    4 5
    5 6
    1 4
    2 3
    3 4
    4 5
    5 6
    Output
    n-hexane
    3-methylpentane

二、算法

  • 1.分析

    分析图片中给出的五个同分异构体,不难看出每个节点(原子)的__度数__(这里采用了图论的说法)可以较好地区分这5个同分异构体。具体情况见如下表格:

    分子类型4度原子个数3度原子个数2度原子 个数1度原子个数
    n-hexane0042
    2-methylpentane0123
    3-methylpentane0123
    2,3-dimethylbutane0204
    2,2-dimethylbutane1014

    由表格不难看出,除了2-methylpentane和 3-methylpentane这两种分子类型无法辨别出以外,其他的都可以通过该表轻松分辨。对于2-methylpentane和 3-methylpentane这两种分子类型,前者的2个2度原子连在一起,后者却没有(当然其他的辨别方法也是可以的)

  • 2.主要步骤

    主要用到了三个数组来存储相关信息:

    int c[7][7];//若两个原子之间有连线,则为1,否则为0
    int num[7];//存储该分子的各个原子的度数
    int cou[5];//存储该分子每种度数的原子个数
    

    对于输入的每一组:

    for(int j=0;j<5;j++)
    {//一边输入,一边更新c的数据和num的数据
    	int a,b;
    	cin>>a>>b;
    	c[a][b]=1;
    	c[b][a]=1;	
    	num[a]++;num[b]++;
    }
    

    利用num数组更新cou数组:

    for(j=1;j<=6;j++) cou[num[j]]++;
    

    利用if-else针对每种情况输出:

    //4度原子只有一个:
    if(cou[4]==1) cout<<"2,2-dimethylbutane"<<endl;
    //3度原子有2个:
    else if(cou[3]==2) cout<<"2,3-dimethylbutane"<<endl;
    //2度原子有4个:
    else if(cou[2]==4) cout<<"n-hexane"<<endl;
    

    对于2-methylpentane和 3-methylpentane这两种分子类型:

    else
    {
    	//找出两个2度原子的编号
    	int l=0,r=0;
    	for(j=1;j<=6;j++)
    	{
    		if(num[j]==2)
    		{
    			if(!l)
    				l=j;
    			else
    				r=j;
    		}
    	}
    	if(c[l][r]==1)
    	{//2度原子是相连的
    		cout<<"2-methylpentane"<<endl;
    	}
    	else
    	{//2度原子并不连的
    		cout<<"3-methylpentane"<<endl;
    	}
    }
    

    需要注意的是,对于每一组都需要事先初始化清空为0,可以用memset函数。

  • 3.测试结果

    在这里插入图片描述

三、总结与收获

  • 取消cin、cout与stdio之间的同步:

    std::ios::sync_with_stdio(false);
    

    但需要注意的是,取消同步之后似乎就不能用stdio里的scanf/printf/getchar……
    出于尝试的目的这次只用了cin/cout来写,感觉上不如scanf/printf好用,遇到要求输出特殊的格式还是后者方便一些。
    查阅到的一些相关方面的博客:
    关于std::ios::sync_with_stdio(false);
    关于C++中ios::sync_with_stdio(false);

  • 清空数组或初始化为0:

    #include<cstring>
    memset(c,0,sizeof(c));
    memset(num,0,sizeof(num));
    memset(cou,0,sizeof(cou));
    

    memset函数在string.h头文件中,对给定的区域按字节进行赋值,所以要是memset(c,2,sizeof(c))如果c数组的每一个元素都是int型,那么每一个元素并不会被赋值为2,相反是一个比较大的数;但是如果对每一个字节都赋值为0或者-1,那么对于每一个int的变量也都是0或-1。此外,还经常用memset(c,63,sizeof(c))来将变量赋值为无穷大(因为复制完之后值比较大,接近int的最高上限)。

四、代码

#include<iostream>
#include<cstdio>
#include<cmath>
#include<cstring>//为了memset 
using namespace std;
#define __ std::ios::sync_with_stdio(false)
int c[7][7];
int num[7];
int cou[5];
int main()
{
	__;
	int T,i,j;
	cin>>T;
	for(i=0;i<T;i++)
	{
		memset(c,0,sizeof(c));
		memset(num,0,sizeof(num));
		memset(cou,0,sizeof(cou));
		for(j=0;j<5;j++)
		{
			int a,b;
			cin>>a>>b;
			c[a][b]=1;
			c[b][a]=1;	
			num[a]++;num[b]++;
		}
		for(j=1;j<=6;j++)
		{
			cou[num[j]]++;
		}
		if(cou[4]==1)
		{
			cout<<"2,2-dimethylbutane"<<endl;
		}
		else if(cou[3]==2)
		{
			cout<<"2,3-dimethylbutane"<<endl;
		}
		else if(cou[2]==4)
		{
			cout<<"n-hexane"<<endl;
		}
		else
		{
			int l=0,r=0;
			for(j=1;j<=6;j++)
			{
				if(num[j]==2)
				{
					if(!l)
						l=j;
					else
						r=j;
				}
			}
			if(c[l][r]==1)
			{
				cout<<"2-methylpentane"<<endl;
			}
			else
			{ 
				cout<<"3-methylpentane"<<endl;
			}
		}
	}
	return 0;
} 
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值