题目:
化学很神奇,以下是烷烃基。
假设如上图,这个烷烃基有6个原子和5个化学键,6个原子分别标号1~6,然后用一对数字 a,b 表示原子a和原子b间有一个化学键。这样通过5行a,b可以描述一个烷烃基
你的任务是甄别烷烃基的类别。
原子没有编号方法。
输入:输入第一行为数据的组数T(1≤T≤200000)。每组数据有5行,每行是两个整数a, b(1≤a,b≤6,a ≤b)
数据保证,输入的烷烃基是以上5种之一
输出:每组数据,输出一行,代表烷烃基的英文名
样例:
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 | 2 | 3 | 4 |
---|---|---|---|---|
n-hexane | 2 | 4 | 0 | 0 |
2-methylpentane | 3 | 2 | 1 | 0 |
3-methylpentane | 3 | 2 | 1 | 0 |
2,3-dimethylbutane | 4 | 0 | 2 | 0 |
2,2-dimethylbutane | 4 | 1 | 0 | 1 |
由此决定用2度点的个数作为区别指标。
但是2-methylpentane和3-methylpentane仍无法区分,所以再细致区分。3-methylpentane中度数为3
的点与两个度数为2的点直接连接,而2-methylpentane中只连接了一个。用此特征得出最终判断结
果。
在输入过程中,除了存储节点外,还需用二维数组存储连接情况,同时统计不同度数的点的个数。
代码:
#include <stdio.h>
#include <string.h>
int ju[7][7];//二维数组,用于存储连接情况
int node[10];//存每个点的度数 ,node[1]~node[6}
int label[10];
int main(){
int n;
scanf("%d",&n);
int a,b;
int d=0,e=0,f=0;
for(int i=0;i<n;i++){
memset(ju,0,sizeof(ju));
memset(node,0,sizeof(node));
memset(label,0,sizeof(label));
d=0,e=0,f=0;
for(int j=0;j<5;j++){
scanf("%d%d",&a,&b);
node[a]++;
node[b]++;
ju[a][b]=1;ju[b][a]=1;//记录连接情况
}
for(int j=1;j<=6;j++){
label[node[j]]++;//统计不同度数的点的个数
}
if(label[2]==4){//如果度数为2的点有四个,以下同理
printf("n-hexane\n");
}
else if(label[2]==2){
//printf("or\n");
for(int m=1;m<=6;m++){
if(node[m]==2&&d==0)
d=m;
else if(node[m]==2&&e==0)//找出两个度为2的点
e=m;
if(node[m]==3)//找出度为3的点
f=m;
}
//printf("d=%d e=%d f=%d\n",d,e,f);
if(ju[d][f]==1&&ju[e][f]==1)//如果度数为3的点同时与两个度数为2的点连接
printf("3-methylpentane\n");
else
printf("2-methylpentane\n");
}
else if(label[2]==0){
printf("2,3-dimethylbutane\n");
}
else if(label[2]==1){
printf("2,2-dimethylbutane\n");
}
}
return 0;
}
总结:
此方法属于暴力求解,代码量也较多,还有很大提升空间。