- 题意:
6个原子5个化学键构成的烷烃基有5种,如图:
6个原子分别标号1-6(没有固定的标号方法),输入5个数对代表5个化学键,输出烷烃基的类别。
- 做法:
根据不同类别烷烃基原子的度数特点区别。不同类别烷烃基1,2,3,4度原子个数如下表
度数 | 1 | 2 | 3 | 4 |
n-hexane | 2 | 4 | ||
3-methylpentane | 3 | 2 | 1 | |
2,2-dimethylbutane | 4 | 1 | 1 | |
2-methylpentane | 3 | 2 | 1 | |
2,3-dimethylbutane | 4 | 2 |
原始的做法:
不忍直视的心路历程:如果没有发现有两种类别1,2,3,4度原子数是一样的,就会直接写代码,当发现单凭统计1,2,3,4度的原子数无法区别3-methylpentane和2-methylpentane时,只能寻找进一步的差别。终于发现两种类别3度原子的相邻的2度原子数不一样,这样可以唯一区分了。由于之前没有保存5个化学键的位置,在输入过程只进行了计数,所以又回头修改保存的数据结构,最终提交了惨不忍睹的代码。
pair数组p保存5个化学键,map结构mp统计6个原子的度数,map结构degree统计1、2、3、4度原子的个数。若1度原子数为2,是n-hexane;若1度原子数为3,在mp找到3度原子,然后在p中找到这个3度原子的相邻原子,借助mp统计其相邻原子中2度原子的个数,若为2,是3-methylpentane,若为1,2-methylpentane;若1度原子数为4,若3度原子数为2,是2,3-dimethylbutane,否则,是2,2-dimethylbutane。
- 代码:
#include<cstdio>
#include<iostream>
#include<map>
using namespace std;
//5个化学键
pair<int,int> p[6];
//1-6号原子的度数
map<int,int> mp={ {1,0},{2,0},{3,0},{4,0},{5,0},{6,0} };
//1、2、3、4度的原子数
map<int,int> degree={ {1,0},{2,0},{3,0},{4,0} };
int main()
{
int n; cin>>n;
int a,b;
for(int i=0;i<n;i++)
{
//初始化
for(int j=1;j<7;j++){
mp[j]=0;
degree[j]=0;
}
//输入
for(int j=1;j<6;j++){
cin>>a>>b;
mp[a]++; mp[b]++;
p[j].first=a; p[j].second=b;
}
//统计1,2,3,4度的原子数
for(int k=1;k<7;k++) degree[mp[k]]++;
//判断
if(degree[1]==2) cout<<"n-hexane"<<endl;
else if(degree[1]==3)
{
//找出三度的原子
int temp=0;//三度原子
for(int k=1;k<7;k++)
{
if(mp[k]==3) temp=k;
}
//找到三度原子的相邻二度原子数
int r=0;//记录三度原子的相邻二度原子数
for(int m=1;m<6;m++)
{
if(p[m].first==temp){
if(mp[p[m].second]==2) r++;
}
else if(p[m].second==temp)
{
if(mp[p[m].first]==2) r++;
}
}
if(r==2) cout<<"3-methylpentane"<<endl;
else if(r==1) cout<<"2-methylpentane"<<endl;
}
else if(degree[1]==4)
{
if(degree[3]==2) cout<<"2,3-dimethylbutane"<<endl;
else cout<<"2,2-dimethylbutane"<<endl;
}
}
return 0;
}
- 提升的做法:其实本质上和上面的思路是一样的,但是不是利用if else 特判,而是直接用一个degree二维数组记录度数之的关系
找到可以唯一特异性标记类别的方法:二维数组degree[i][j]记录有多少对i度和j度原子相邻,见下表,标下划线的为可以特异性区分的特征。
n-hexane
1 | 2 | 3 | 4 | |
---|---|---|---|---|
1 | 2 | |||
2 | 2 | 3 | ||
3 | ||||
4 |
3-methylpentane
1 | 2 | 3 | 4 | |
---|---|---|---|---|
1 | 2 | 1 | ||
2 | 2 | 2 | ||
3 | 1 | 2 | ||
4 |
2,2-dimethylbutane
1 | 2 | 3 | 4 | |
---|---|---|---|---|
1 | 1 | 3 | ||
2 | 1 | 1 | ||
3 | ||||
4 | 3 | 1 |
2-methylpentane
1 | 2 | 3 | 4 | |
---|---|---|---|---|
1 | 1 | 2 | ||
2 | 1 | 1 | 1 | |
3 | 2 | 1 | ||
4 |
2,3-dimethylbutane
1 | 2 | 3 | 4 | |
---|---|---|---|---|
1 | 4 | |||
2 | ||||
3 | 4 | 1 | ||
4 |
提升的代码:
#include<cstdio>
#include<iostream>
#include<map>
#include<cstring>
using namespace std;
//5个化学键
pair<int,int> p[6];
//1-6号原子的度数
map<int,int> mp={ {1,0},{2,0},{3,0},{4,0},{5,0},{6,0} };
//度数与度数之间的关系
int degree[5][5];
int main()
{
int n; cin>>n;
int a,b;
for(int i=0;i<n;i++)
{
//初始化
for(int j=1;j<=6;j++) mp[j]=0;
memset(degree,0,sizeof(degree));
//输入
for(int j=1;j<=5;j++){
cin>>a>>b;
mp[a]++; mp[b]++;
p[j].first=a; p[j].second=b;
}
//统计多少对i度和j度原子相邻
for(int j=1;j<=5;j++){
degree[mp[p[j].first]][mp[p[j].second]]++;
if(mp[p[j].first]!=mp[p[j].second]) degree[mp[p[j].second]][mp[p[j].first]]++;
}
//判断
if(degree[2][2]==3) cout<<"n-hexane"<<endl;
else if(degree[1][3]==1) cout<<"3-methylpentane"<<endl;
else if(degree[1][4]==3) cout<<"2,2-dimethylbutane"<<endl;
else if(degree[1][3]==2) cout<<"2-methylpentane"<<endl;
else if(degree[1][3]==4) cout<<"2,3-dimethylbutane"<<endl;
}
return 0;
}
- 总结:
对于这种看上去目标明确十分简单的题,最容易没有清晰思路直接写代码,最终可能可以解决问题,但结构会十分混乱。
写代码之前,要确定好:需要存什么?用什么存?输入经过怎样的过程可以得到结果?