欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

week2实验——模拟

程序员文章站 2022-07-12 14:58:30
...

题目1
烷烃基的判断。需要判断的烷烃基一共有5种。原子没有固定的编号。五种烷烃基的结构简式如下:
week2实验——模拟
输入
输入第一行为数据的组数T(1≤T≤200000)。每组数据有5行,每行是两个整数a, b(1≤a,b≤6,a ≤b)

数据保证,输入的烷烃基是以上5种之一

输出
每组数据,输出一行,代表烷烃基的英文名
解题思路
由于原子没有固定的编号,所以判断方法是根据每个原子邻接点的数量来判断。其中,大部分的烷烃基可以通过最高邻接点的邻接总数或者邻接点为2的原子个数一次判断。2-methylpentane和3-methylpentane在临接点的形式上是一致的,需要额外通过邻接数为3的原子的邻接点的性质(与它邻接的点邻接数为2的个数)来进行二次判断。
代码

#include <cstdio>

using namespace std;

int main()
{
	int n;
	scanf("%d",&n);
	int a,b;
	int linjie[7]={0,0,0,0,0,0,0};
	int map[7][7];
	int count[5]={0,0,0,0,0};
	for(int i=1;i<=6;i++)
	{
		for(int j=1;j<=6;j++)
		    map[i][j]=0;
	}
	for(int i=1;i<=n;i++)
	{
		for(int j=1;j<=5;j++)
		{
			scanf("%d %d",&a,&b);
			linjie[a]++;
			linjie[b]++;
			map[a][b]=1;
			map[b][a]=1;			
		}
		for(int k=1;k<=6;k++)
		{
			count[linjie[k]]++;
			if(linjie[k]==3)
			{
				for(int l=1;l<=6;l++)
				{
					if(map[k][l]==1&&linjie[l]==2) 
					{
						count[0]++;
					}
				}
			}
		}
		if(count[4]==1) printf("2,2-dimethylbutane\n");
		else if(count[3]==2) printf("2,3-dimethylbutane\n");
		else if(count[2]==4) printf("n-hexane\n");
		else if(count[3]==1&&count[0]==2) printf("3-methylpentane\n");
		else printf("2-methylpentane\n");
		for(int p=1;p<=6;p++)
		    linjie[p]=0;
		for(int p=0;p<=4;p++)
		    count[p]=0;
	    for(int i=1;i<=6;i++)
	    {
		    for(int j=1;j<=6;j++)
		        map[i][j]=0;
	    }
	}
}

题目2
oj评测系统的模拟,要求根据输入的有关数据,算出某人做出的题目个数以及罚时。
输入
例如某次考试一共八道题(A,B,C,D,E,F,G,H),每个人做的题都在对应的题号下有个数量标记,负数表示该学生在该题上有过的错误提交次数但到现在还没有AC,正数表示AC所耗的时间,如果正数a跟上了一对括号,里面有个正数b,则表示该学生AC了这道题,耗去了时间a,同时曾经错误提交了b次。例子可见下方的样例输入与输出部分。
输入数据包含多行,第一行是共有的题数n(1≤n≤12)以及单位罚时m(10≤m≤20),之后的每行数据描述一个学生的信息,首先是学生的用户名(不多于10个字符的字串)其次是所有n道题的得分现状。
输出
根据这些学生的得分现状,输出一个实时排名。实时排名显然先按AC题数的多少排,多的在前,再按时间分的多少排,少的在前,如果凑巧前两者都相等,则按名字的字典序排,小的在前。每个学生占一行,输出名字(10个字符宽),做出的题数(2个字符宽,右对齐)和时间分(4个字符宽,右对齐)。名字、题数和时间分相互之间有一个空格。数据保证可按要求的输出格式进行输出。
解题思路
第一行的两个数直接读入即可。
从第二行开始,由于输入的数据格式比较复杂而且不统一,因此我将输入的每一行看成若干个字符串,第一个字符串为学生的名字,之后的字符串为该学生做题的情况。现在的问题是将字符转化为整数进行运算。而字符0-9的ASCII码减48即为数字0-9。总之,需要注意以下几点:
1.使用一个变量n储存该题的得分,每次读字符串得到数x(不是括号里的数),按照n*10+x-48更新n。
2.左括号代表额外罚时的出现,此时需要用另一个变量m保存罚时,更新方法同上。
3.出现符号则跳过该数据。
最后将得出的m和n求和并存到vector中并排序即可。
代码

#include <cstdio>
#include <queue>
#include <algorithm>
#include <string.h>

using namespace std;

class student
{
public:
	char *name;
	int score;
	int penalty;
	student(char* a,int b,int c)
	{
		name=new char[20];
		memset(name,0,20);
		for(int i=0;a[i]!=0;i++)
		{
			name[i]=a[i];
		}
		score=b;
		penalty=c;
	};
	bool operator <(const student& p) const
	{
		if(score!=p.score) return score>p.score;
		else if(penalty!=p.penalty) return penalty<p.penalty;
		else return(strcmp(name,p.name)<0);
	};
};

int main()
{
	int n,m;
	int score=0,penalty=0;
	int punish_time=0;
	bool sp=false;
	int thepenalty=0;
	scanf("%d %d",&n,&m);
	char name[20];
	memset(name,0,20);
	char **si;
	si=new char*[n+1];
	vector<student> v;
	for(int i=1;i<=n;i++)
	{
		si[i]=new char[20];
		memset(si[i],0,20);
	}
	while(scanf("%s",name)!=EOF)
	{
		for(int i=1;i<=n;i++)
		{
			scanf("%s",si[i]);
			//printf("%s\n",si[i]);
			int j=0;
			while(si[i][j]!=0)
			{
				//printf("si[i][j]=%d\n",si[i][j]);
				if(si[i][j]==45) break;
				else if(si[i][j]>=48&&si[i][j]<=57&&!sp) {penalty=penalty*10+(si[i][j]-48);} 
				else if(si[i][j]>=48&&si[i][j]<=57&&sp) {punish_time=punish_time*10+(si[i][j]-48)*m;}
				else if(si[i][j]=='(') sp=true;
				else if(si[i][j]==')') 
				{
					penalty+=punish_time;
					punish_time=0;
					sp=false;
				}
				else ;
				j++;
			}
			if(penalty!=0) score++;
			punish_time=0;
			thepenalty+=penalty;
			penalty=0;
			sp=false;
		}
		student* newstudent=new student(name,score,thepenalty);
		score=0;
		thepenalty=0;
		//printf("nn=%s\n",newstudent.name);
		v.push_back(*newstudent);
		memset(name,0,20);
	}
	sort(v.begin(),v.end());
	for(int i=0;i<v.size();i++)
	{
		printf("%-10s %2d %4d\n",v[i].name,v[i].score,v[i].penalty);
	}
	return 0;
}

题目3
发牌模拟。要求根据已知的牌堆以及发牌人的位置,按照升序输出每个玩家手中的牌。
输入
输入包含多组数据
每组数据的第一行包含一个大写字符,表示发牌员是谁。如果该字符为‘#’则表示输入结束。
接下来有两行,每行有52个字符,表示了26张牌,两行加起来一共52张牌。每张牌都由两个字符组成,第一个字符表示花色,第二个字符表示数值。
输出
输出多组数据发牌的结果,每组数据之后需要额外多输出一个空行!!!!!
每组数据应该由24行的组成,输出按照顺时针方向,始终先输出South Player的结果,每位玩家先输出一行即玩家名称(东南西北),接下来五行,第一行和第五行输出固定格式(见样例),第二行和第四行按顺序和格式输出数值(见样例),第三行按顺序和格式输出花色(见样例)。
样例输入/输出
略。
解题思路
本题的字符过多,但是由于牌(J,Q,K,A)非常的不规则,同时花色之间还有大小关系。所以为了方便,我使用了map容器,将输入的字符按照大小关系,分别映射到一个整数上。这样,在编写排序的时候,就可以通过查找map获得对应的整数,进行排序了。对于发牌员的模拟比较的简单。由于是转圈发牌,所以,可以将4个人以N为起始,按照顺时针标记为0,1,2,3。根据发牌数和起始发牌位置进行取模运算得到该牌应该发到的玩家。对于每一个玩家收到的牌,都分别存到一个vector中。再发完牌后进行排序即可。
代码

#include <cstdio>
#include <map>
#include <queue>
#include <algorithm>

using namespace std;

map<char,int> mp;
map<char,int> position;

class card
{
public:
	char color;
	char point;	
	card(char a,char b)
	{
		color=a;
		point=b;
	};
	bool operator <(const card& p) const
	{
		if(mp[color]==mp[p.color]) return mp[point]<mp[p.point];
		else return mp[color]<mp[p.color];
	};
};



int main()
{
	mp['2']=2;
    mp['3']=3;
    mp['4']=4;
    mp['5']=5;
    mp['6']=6;
    mp['7']=7;
    mp['8']=8;
    mp['9']=9;
    mp['T']=10;
    mp['J']=11;
    mp['Q']=12;
    mp['K']=13;
    mp['A']=14;
    mp['C']=15;
    mp['D']=16;
    mp['S']=17;
    mp['H']=18;
    position['N']=0;
    position['E']=1;
    position['S']=2;
    position['W']=3;
    vector<card> group[4];
    char sender;
    scanf("%c",&sender);
    getchar();
    int start=position[sender];
    char a,b;
    int count=0;
    scanf("%c",&a);
    while(1)
    {
    	count++;
    	scanf("%c",&b);
    	card newcard(a,b);
    	if(count==26||count==52) getchar();
    	//printf("count=%d\na=%c,point=%c\n",count,a,newcard.point);
    	group[(start+count)%4].push_back(newcard);
    	if(count==52)
    	{
    		for(int i=0;i<4;i++)
	        {
		        vector<card>::iterator it=group[i].begin();
		        sort(it,it+13);
		    }
		    count=0;
		    for(int i=0;i<4;i++)
		    {
		    	if(i==0) printf("South player:\n");
		    	else if(i==1) printf("West player:\n");
		    	else if(i==2) printf("North player:\n");
		    	else if(i==3) printf("East player:\n");
		    	for(int j=1;j<=5;j++)
		    	{
		    		if(j==1||j==5) printf("+---+---+---+---+---+---+---+---+---+---+---+---+---+\n");
		    		else if(j==2||j==4)
		    		{
		    			for(int k=0;k<13;k++)
		    			{
		    				printf("|%c %c",group[(2+i)%4][k].point,group[(2+i)%4][k].point);
						}
						printf("|\n");
					}
					else
					{
						for(int k=0;k<13;k++)
		    			{
		    				printf("| %c ",group[(2+i)%4][k].color);
						}
						printf("|\n");
					}
				}
			}
			printf("\n");
			for(int i=0;i<4;i++)
			{
				group[i].clear();
			}
		    count=0;
		    scanf("%c",&sender);
		    getchar();
		    start=position[sender];
		    if(sender=='#') break;
		}
		scanf("%c",&a);
	}
	return 0;
}

总结
三道小模拟,题目不算很难。通过这三个题,我对map,vector等C++STL容器有了更加深入的理解。自我感觉对模拟题还需要加强,做的时候不是很顺。虽然思路简单,但打起代码的时候还是不太顺利。以后还是要多练。