程序设计思维与实践 Week9 作业

A - 咕咕东的目录管理器

问题描述
咕咕东的雪梨电脑的操作系统在上个月受到宇宙射线的影响,时不时发生故障,他受不了了,想要写一个高效易用零bug的操作系统 —— 这工程量太大了,所以他定了一个小目标,从实现一个目录管理器开始。前些日子,东东的电脑终于因为过度收到宇宙射线的影响而宕机,无法写代码。他的好友TT正忙着在B站看猫片,另一位好友瑞神正忙着打守望先锋。现在只有你能帮助东东!

初始时,咕咕东的硬盘是空的,命令行的当前目录为根目录 root。

目录管理器可以理解为要维护一棵有根树结构,每个目录的儿子必须保持字典序。

在这里插入图片描述

现在咕咕东可以在命令行下执行以下表格中描述的命令:
在这里插入图片描述

输入

输入文件包含多组测试数据,第一行输入一个整数表示测试数据的组数 T (T <= 20);

每组测试数据的第一行输入一个整数表示该组测试数据的命令总数 Q (Q <= 1e5);

每组测试数据的 2 ~ Q+1 行为具体的操作 (MKDIR、RM 操作总数不超过 5000);

面对数据范围你要思考的是他们代表的 “命令” 执行的最大可接受复杂度,只有这样你才能知道你需要设计的是怎样复杂度的系统。

输出
每组测试数据的输出结果间需要输出一行空行。注意大小写敏感。

时空限制
Time limit 6000 ms

Memory limit 1048576 kB

样例输入

1
22
MKDIR dira
CD dirb
CD dira
MKDIR a
MKDIR b
MKDIR c
CD ..
MKDIR dirb
CD dirb
MKDIR x
CD ..
MKDIR dirc
CD dirc
MKDIR y
CD ..
SZ
LS
TREE
RM dira
TREE
UNDO
TREE

样例输出

OK
ERR
OK
OK
OK
OK
OK
OK
OK
OK
OK
OK
OK
OK
OK
9
dira
dirb
dirc
root
dira
a
b
c
dirb
x
dirc
y
OK
root
dirb
x
dirc
y
OK
root
dira
a
b
c
dirb
x
dirc
y

解题思路

  • 本题主要难在撤销操作和其他时间复杂度有要求的操作
  • 因为每个目录的儿子必须保持字典序,插入一个排序一次会浪费时间,所以使用map<string,int>存储目录下的“儿子”,建立string到int的映射,自动排序。
  • UNDO:只能撤销插入、删除、进入子目录。所以用vector储存,每次进行上述三种操作时把对应的操作插入vector;UNDO时取vector尾元素,得到进行的操作,插入边则删除它,删除边则恢复它,进入子目录则返回根目录。用point结构体储存操作名称、当前位置和操作的目录。
  • SZ:如果每次都遍历一次所有的目录获得size,则每次查询的最大计算量即为树的最大规模,5000;最大查询次数为1e5-5000=9.5e4;最大计算量约为50001e520=1e10,超时。所以每次在每个节点增加一个变量sz,加上该节点后的size;输出"根节点"的sz即可。
  • 用update函数更新size,需要从插入处往上更新,所以在节点中加入储存父节点的变量fa;根目录的父节点置为-1;
  • TREE:如果每一次都遍历一次,得到结果,则每次的最大计算量即树的最大规模,5000;最大查询次数9.5e4,最大计算量约为50001e520=1e10,超时。所以利用懒更新的方法,将结果储存在数组中,并记录值是否更新过(是否进行过插入删除);每次调用该操作时更新过则重新遍历,未更新过则直接输出。
  • MKDIR:搜索是否存在要插入的子目录,是则输出错误信息,不存在则对应位置插入即可。将该操作存入vector;调用update函数更新sz,并记录走过的节点为需要更新。
  • RM:搜索要删除的子目录是否存在,不存在则输出错误信息,存在则删除对应的一条边即可(如果删除了对应节点,则该节点下面的所有子节点都没了,恢复十分困难);调用update函数更新sz,并记录走过的节点为需要更新。
  • CD:进入子目录s(检验是否存在)或者返回上层目录(检验是否为根目录),储存操作为undo做准备,更新now的位置即可。
  • LS:没有子目录则输出empty;利用map自带的迭代器,小于10个则全输出,大于则输出前五、后五个。

完整代码

#include <iostream>
#include <cstring>
#include <map>
#include <vector>
using namespace std;

struct Directory
{
	string name;	//名称
	map<string,int>mp;	//后代的名称->编号,自动排序 
	int fa,sz;	//父亲节点,子树的规模
	vector<string> pre,bck; //存前序遍历的前后序列 
	bool tag;	//记录是否被更新过
};
 
Directory node[200000];
//node[i]和map中的second相对应
 
int now;	//当前节点
int idx;	//最新节点

struct point	//用于undo储存信息
{
	string name;	//操作名称
	int now;	
	int next;	//要操作的目录位置
};

vector<point> v;//记录可以进行undo的操作 


void update(int id,int num)	//更新size,即 id处的节点增加了num 
{//id不到最头上 
	while(id!=-1)
	{
		node[id].tag=0;//标记为未改变 
		node[id].sz+=num;//加上num 
		id=node[id].fa;//往上走 
	}
}


void MKDIR(string &s)	//在当前目录下创建一个子目录s
{
	if(node[now].mp.count(s)==1)	//存在节点
		cout<<"ERR"<<endl;
	else
	{
		node[now].mp.insert(pair<string,int>(s,idx));
		update(now,1);
		
		//在node[idx]创建新节点
		node[idx].name=s;
		node[idx].fa=now;
		node[idx].sz=1;
		node[idx].tag=0;//标记为需要重新遍历 
		node[idx].mp.clear();
		node[idx].pre.clear();
		node[idx].bck.clear();
		
		//将操作放入undo的vector中
		point p;
		p.name="MKDIR",p.now=now,p.next=idx;
		v.push_back(p); 
		idx++;
		cout<<"OK"<<endl;
	}
}

void RM(string &s)	//在当前目录下删除子目录s
{
	if(node[now].mp.count(s)==1)	//存在节点
	{
		int indexOfS=node[now].mp[s];
		node[now].mp.erase(s);//只删除边 
		update(now,(-1)*node[indexOfS].sz);//每个节点减少删除节点的size
		 
		//将操作放入undo的vector中
		point p;
		p.name="RM",p.now=now,p.next=indexOfS;
		v.push_back(p); 
		cout<<"OK"<<endl;
	}
	else	cout<<"ERR"<<endl;
}

void CD(string &s)	//进入子目录s,储存操作为undo做准备,更新now 
{
	if(s=="..")	//返回上级目录
	{
		if(node[now].fa==-1)	//根目录
			cout<<"ERR"<<endl;
		else
		{
			//将操作放到undo的vector中
			point p;
			p.name="CD",p.now=now,p.next=node[now].fa;
			v.push_back(p);
			now=node[now].fa;//更新now 
			cout<<"OK"<<endl;
		}
	}
	else //进入子目录s
	{
		if(node[now].mp.count(s)==1)	//存在s才进入 
		{
			//将操作放到undo的vector中
			point p;
			p.name="CD",p.now=now,p.next=node[now].mp[s];
			v.push_back(p);
			now=node[now].mp[s];//更新now 
			cout<<"OK"<<endl;
		}
		else cout<<"ERR"<<endl;
	}
}


void SZ()	//输出当前目录的大小
{
	cout<<node[now].sz<<endl;
}


void LS()	//输出当前目录的直接子目录名
{
	if(node[now].mp.size()==0)	//没有子目录
		cout<<"EMPTY"<<endl;
	else if(node[now].mp.size()>=1&&node[now].mp.size()<=10)	//全部输出
	{
		for(map<string,int>::iterator it=node[now].mp.begin(); it!=node[now].mp.end(); it++)
			cout<<it->first<<endl;
	}
	else //输出前五个和后五个
	{
		//前五个
		map<string,int>::iterator it=node[now].mp.begin();
		for(int i=1; i<=5; i++)
		{
			cout<<it->first<<endl;
			it++;
		}
		cout<<"..."<<endl;
		//后五个
		it=node[now].mp.end();
		for(int i=1; i<=5; i++)
			it--;
		for(int i=1; i<=5; i++)
		{
			cout<<it->first<<endl;
			it++;
		}
	}
}


void alltrack(int id,vector<string> &pre)	//前序遍历id子树(小于10个时)
{
	pre.push_back(node[id].name);
	for(map<string,int>::iterator it=node[id].mp.begin(); it!=node[id].mp.end(); it++)
		alltrack(it->second,pre);
} 

void pretrack(int id,vector<string> &pre,int &num)	//前序遍历id子树,求出前五个 
{
	pre.push_back(node[id].name);
	num--;
	if(num==0)	return;
	for(map<string,int>::iterator it=node[id].mp.begin(); it!=node[id].mp.end(); it++)
	{
		pretrack(it->second,pre,num);
		if(num==0)	break;
	}
}

void bcktrack(int id,vector<string> &bck,int &num)	//右左根遍历id子树,求出后五个 
{
	map<string,int>::iterator it=node[id].mp.end();	
	int n=node[id].mp.size();
	for(int i=0;i<n;i++)
	{
		it--;
		bcktrack(it->second,bck,num);
		if(num==0)	return;
	}
	bck.push_back(node[id].name);
	num--;
}

void pushdown(int id)	//遍历id子树 
{
	node[id].pre.clear();
	node[id].bck.clear();
	if(node[id].sz<=10)
		alltrack(id,node[id].pre);
	else
	{
		int num=5;
		pretrack(id,node[id].pre,num);
		num=5;
		bcktrack(id,node[id].bck,num);
	}
	node[id].tag=1;//标记为已改变,即最新 
}

void TREE()	//输出以当前目录为根的子树的前序遍历结果
{
	if(!node[now].tag)	//需要遍历就去遍历 
		pushdown(now);
	if(node[now].sz==1)	//子目录为空
		cout<<"EMPTY"<<endl;
	else if(node[now].sz>1&&node[now].sz<=10) 
	{
		for(int i=0;i<node[now].pre.size();i++)
			cout<<node[now].pre[i]<<endl;
	}
	else
	{
		for(int i=0;i<5;i++)
			cout<<node[now].pre[i]<<endl;
		cout<<"..."<<endl;
		for(int i=4;i>=0;i--)
			cout<<node[now].bck[i]<<endl;
	}
}
void UNDO()	//撤销最近一个成功执行的MKDIR或RM或CD
{
	if(v.size()==0)	//没有操作
		cout<<"ERR"<<endl;
	else
	{
		point p=v[v.size()-1];//队尾弹出 
		v.pop_back();
		cout<<"OK"<<endl;
		if(p.name=="MKDIR")	//要删除
		{ 
			update(p.now,(-1)*node[p.next].sz);
			node[p.now].mp.erase(node[p.next].name);
		}
		else if(p.name=="RM")	//要添加
		{
			update(p.now,node[p.next].sz);
			node[p.now].mp[node[p.next].name]=p.next;
		}
		else	//要返回
			now=p.now;
	}
}
int main()
{
	ios::sync_with_stdio(false);
	int t;
	cin>>t;
	for(int t1=0; t1<t; t1++)
	{
		if(t1!=0)	//测试数据之间输出空行 
			cout<<endl;	
		int q;
		cin>>q;
		//初始化
		//根节点为node[0],其父亲为-1
		now=0,idx=1;
		node[0].name="root",node[0].fa=-1,node[0].sz=1,node[0].tag=0;
		node[0].pre.clear(),node[0].bck.clear(),node[0].mp.clear();
		v.clear(); 
		for(int q1=0; q1<q; q1++)
		{
			string op;
			cin>>op;
			if(op=="MKDIR")
			{
				string s;
				cin>>s;
				MKDIR(s);
			}
			else if(op=="RM")
			{
				string s;
				cin>>s;
				RM(s);
			}
			else if(op=="CD")
			{
				string s;
				cin>>s;
				CD(s);
			}
			else if(op=="SZ")
				SZ();
			else if(op=="LS")
				LS();
			else if(op=="TREE")
				TREE();
			else if(op=="UNDO")
				UNDO();
		}
	}
}

B - 东东学打牌

问题描述
最近,东东沉迷于打牌。所以他找到 HRZ、ZJM 等人和他一起打牌。由于人数众多,东东稍微修改了亿下游戏规则:

所有扑克牌只按数字来算大小,忽略花色。
每张扑克牌的大小由一个值表示。A, 2, 3, 4, 5, 6, 7, 8, 9, 10, J, Q, K 分别指代 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13。
每个玩家抽得 5 张扑克牌,组成一手牌!(每种扑克牌的张数是无限的,你不用担心,东东家里有无数副扑克牌)
理所当然地,一手牌是有不同类型,并且有大小之分的。

举个栗子,现在东东的 “一手牌”(记为 α),瑞神的 “一手牌”(记为 β),要么 α > β,要么 α < β,要么 α = β。

那么这两个 “一手牌”,如何进行比较大小呢?首先对于不同类型的一手牌,其值的大小即下面的标号;对于同类型的一手牌,根据组成这手牌的 5 张牌不同,其值不同。下面依次列举了这手牌的形成规则:

1.大牌:这手牌不符合下面任一个形成规则。如果 α 和 β 都是大牌,那么定义它们的大小为组成这手牌的 5 张牌的大小总和。

2.对子:5 张牌中有 2 张牌的值相等。如果 α 和 β 都是对子,比较这个 “对子” 的大小,如果 α 和 β 的 “对子” 大小相等,那么比较剩下 3 张牌的总和。

3.两对:5 张牌中有两个不同的对子。如果 α 和 β 都是两对,先比较双方较大的那个对子,如果相等,再比较双方较小的那个对子,如果还相等,只能比较 5 张牌中的最后那张牌组不成对子的牌。

4.三个:5 张牌中有 3 张牌的值相等。如果 α 和 β 都是 “三个”,比较这个 “三个” 的大小,如果 α 和 β 的 “三个” 大小相等,那么比较剩下 2 张牌的总和。

5.三带二:5 张牌中有 3 张牌的值相等,另外 2 张牌值也相等。如果 α 和 β 都是 “三带二”,先比较它们的 “三个” 的大小,如果相等,再比较 “对子” 的大小。

6.炸弹:5 张牌中有 4 张牌的值相等。如果 α 和 β 都是 “炸弹”,比较 “炸弹” 的大小,如果相等,比较剩下那张牌的大小。

7.顺子:5 张牌中形成 x, x+1, x+2, x+3, x+4。如果 α 和 β 都是 “顺子”,直接比较两个顺子的最大值。

8.龙顺:5 张牌分别为 10、J、Q、K、A。

作为一个称职的魔法师,东东得知了全场人手里 5 张牌的情况。他现在要输出一个排行榜。排行榜按照选手们的 “一手牌” 大小进行排序,如果两个选手的牌相等,那么人名字典序小的排在前面。

不料,此时一束宇宙射线扫过,为了躲避宇宙射线,东东慌乱中清空了他脑中的 Cache。请你告诉东东,全场人的排名

输入
输入包含多组数据。每组输入开头一个整数 n (1 <= n <= 1e5),表明全场共多少人。
随后是 n 行,每行一个字符串 s1 和 s2 (1 <= |s1|,|s2| <= 10), s1 是对应人的名字,s2 是他手里的牌情况。

输出
对于每组测试数据,输出 n 行,即这次全场人的排名。

样例输入

3
DongDong AAA109
ZJM 678910
Hrz 678910

样例输出

Hrz
ZJM
DongDong

解题思路

  • 本题难度不大,只是较为复杂
  • 注意从8到1条件是逐渐“变小“的,比如考虑是否为2时不需要考虑是不是3,所以从8到1依次判断即可。
  • 结构体存储名字、扑克牌、分数即各种类别的牌对应的比较指标。
  • 给所有扑克牌赋类别,比较即可。

完整代码

#include<iostream>
#include<cstring>
#include<algorithm>
using namespace std;

struct People
{
	char name[11];//名字 
	int s[5];//扑克牌
	int mark;//分数
	
	int shunzi;//存最大值
	int boom[2];//boom[0]为炸弹的牌,boom[1]为另一个
	int sandaier[2];//0为'3',1为'2' 
	int sange[2];//0为'3',1为'2'的和 
	int liangdui[3];//0为大对,1为小对,2为单独
	int duizi[2];//0为对子,1为剩余和
	int dapai;//5个总和 
	
	void init()
	{
		memset(name,0,sizeof(name));
		memset(s,0,sizeof(s));
		mark=0;
	
	}
};
People p[100010];
bool xiaoyu(People a,People b)//根据种类比较 ,return a<b
{
if(a.mark!=b.mark)
	return a.mark<b.mark;

//相等	
	switch(a.mark)
	{
	case 1:
		if(a.dapai!=b.dapai)
		return a.dapai<b.dapai;
		break;
	
	case 2:
		if(a.duizi[0]!=b.duizi[0])
			return a.duizi[0]<b.duizi[0];
			
		if(a.duizi[1]!=b.duizi[1])
			return a.duizi[1]<b.duizi[1];
		
		break;
	
	case 3:
		if(a.liangdui[0]!=b.liangdui[0])
			return 	a.liangdui[0]<b.liangdui[0];
			
		if(a.liangdui[1]!=b.liangdui[1])
			return 	a.liangdui[1]<b.liangdui[1];
			
		if(a.liangdui[2]!=b.liangdui[2])
			return 	a.liangdui[2]<b.liangdui[2];
			
		break;
	
	case 4:
		if(a.sange[0]!=b.sange[0])
			return 	a.sange[0]<b.sange[0];
		
		if(a.sange[1]!=b.sange[1])
			return 	a.sange[1]<b.sange[1];
		
		break;	
	
	case 5:
		if(a.sandaier[0]!=b.sandaier[0])
			return 	a.sandaier[0]<b.sandaier[0];
		
		if(a.sandaier[1]!=b.sandaier[1])
			return 	a.sandaier[1]<b.sandaier[1];
		
		break;	
		
	case 6:
		if(a.boom[0]!=b.boom[0])
			return 	a.boom[0]<b.boom[0];
		if(a.boom[1]!=b.boom[1])
			return 	a.boom[1]<b.boom[1];
		break;	
	
	case 7:
		if(a.shunzi!=b.shunzi)
			return 	a.shunzi<b.shunzi;
		
		break;		
	
	}

	int l1=strlen(a.name),l2=strlen(b.name);
		for(int ii=0;ii<min(l1,l2);ii++)
		{
			if(a.name[ii]==b.name[ii]) continue;
			if(a.name[ii]>b.name[ii]) return true;
			if(a.name[ii]<b.name[ii]) return false;
		}
		//都相等,比长度,长度小的获胜 
		if(l1>l2) return true;
		return false;


}

void judgetype(int i)
{
	sort(p[i].s,p[i].s+5);
//	for(int i=0;i<5;i++)
//	cout<<p[i].s[i]<<" ";cout<<endl; 
	if(p[i].s[0]==1 && p[i].s[1]==10 && p[i].s[2]==11&&p[i].s[3]==12&&p[i].s[4]==13)
	{p[i].mark=8;
	}
	
	else if(p[i].s[0]==p[i].s[1] && p[i].s[1]==p[i].s[2] && p[i].s[2]==p[i].s[3] && p[i].s[3]==p[i].s[4])
	{
	p[i].mark=1;p[i].dapai=p[i].s[0]+p[i].s[1]+p[i].s[2]+p[i].s[3]+p[i].s[4];}       
	
	
		
	else if(p[i].s[0]==p[i].s[1]&&p[i].s[1]==p[i].s[2]&&p[i].s[2]==p[i].s[3]&&p[i].s[3]!=p[i].s[4])
		{p[i].mark=6;
		p[i].boom[0]=p[i].s[0];
		p[i].boom[1]=p[i].s[4];}
		
	else if(p[i].s[0]==p[i].s[1]&&p[i].s[1]==p[i].s[2]&&p[i].s[2]==p[i].s[4]&&p[i].s[3]!=p[i].s[4])
		{p[i].mark=6;
		p[i].boom[0]=p[i].s[0];
		p[i].boom[1]=p[i].s[3]; }
		
	else if(p[i].s[0]==p[i].s[1]&&p[i].s[1]==p[i].s[3]&&p[i].s[3]==p[i].s[4]&&p[i].s[2]!=p[i].s[4])
		{p[i].mark=6;
		p[i].boom[0]=p[i].s[0];
		p[i].boom[1]=p[i].s[2]; }
		
	else if(p[i].s[1]==p[i].s[2]&&p[i].s[2]==p[i].s[3]&&p[i].s[3]==p[i].s[4]&&p[i].s[0]!=p[i].s[4])
		{p[i].mark=6;
		p[i].boom[0]=p[i].s[1];
		p[i].boom[1]=p[i].s[0]; }
		
	else if(p[i].s[0]==p[i].s[2]&&p[i].s[2]==p[i].s[3]&&p[i].s[3]==p[i].s[4]&&p[i].s[1]!=p[i].s[4])
		{p[i].mark=6;
		p[i].boom[0]=p[i].s[0];
		p[i].boom[1]=p[i].s[1]; }	
		
	else if(p[i].s[1]==p[i].s[0]+1&&p[i].s[2]==p[i].s[1]+1&&p[i].s[3]==p[i].s[2]+1&&p[i].s[4]==p[i].s[3]+1)
		{p[i].mark=7;p[i].shunzi=p[i].s[4]; }	
		
	else if(p[i].s[0]==p[i].s[1]&&p[i].s[1]==p[i].s[2] && p[i].s[3]==p[i].s[4]&&p[i].s[0]!=p[i].s[3])
		{
		p[i].mark=5;
		p[i].sandaier[0]=p[i].s[0];
		p[i].sandaier[1]=p[i].s[3]; 
		} 

	else if(p[i].s[0]==p[i].s[1]  &&  p[i].s[2]==p[i].s[3]&&p[i].s[3]==p[i].s[4] && p[i].s[0]!=p[i].s[3])
		{
		p[i].mark=5;
		p[i].sandaier[0]=p[i].s[2];
		p[i].sandaier[1]=p[i].s[0]; 
		} 
		
	else if(p[i].s[0]==p[i].s[1]&&p[i].s[1]==p[i].s[2])
		{
		p[i].mark=4;
		p[i].sange[0]=p[i].s[0];
		p[i].sange[1]=p[i].s[3]+p[i].s[4]; 
		}

	else if(p[i].s[1]==p[i].s[2]&&p[i].s[2]==p[i].s[3])
		{ 
		p[i].mark=4;
		p[i].sange[0]=p[i].s[1];
		p[i].sange[1]=p[i].s[0]+p[i].s[4]; 
		}	

	else if(p[i].s[2]==p[i].s[3]&&p[i].s[3]==p[i].s[4])
		{
		p[i].mark=4;
		p[i].sange[0]=p[i].s[2];
		p[i].sange[1]=p[i].s[0]+p[i].s[1]; 
		}

	else if(p[i].s[0]==p[i].s[1]&&p[i].s[2]==p[i].s[3])
		{
		p[i].mark=3;
		p[i].liangdui[0]=p[i].s[3];
		p[i].liangdui[1]=p[i].s[1];
		p[i].liangdui[2]=p[i].s[4]; 
		}

	else if(p[i].s[1]==p[i].s[2]&&p[i].s[3]==p[i].s[4])
		{
		p[i].mark=3;
		p[i].liangdui[0]=p[i].s[3];
		p[i].liangdui[1]=p[i].s[1];
		p[i].liangdui[2]=p[i].s[0]; 
		}
	
		else if(p[i].s[0]==p[i].s[1]&&p[i].s[3]==p[i].s[4])
		{
		p[i].mark=3;
		p[i].liangdui[0]=p[i].s[3];
		p[i].liangdui[1]=p[i].s[1];
		p[i].liangdui[2]=p[i].s[2]; 
		}
		
		else if(p[i].s[0]==p[i].s[1])
		{
		p[i].mark=2;
		p[i].duizi[0]=p[i].s[0];
		p[i].duizi[1]=p[i].s[2]+p[i].s[3]+p[i].s[4]; 
		}
	
		else if(p[i].s[1]==p[i].s[2])
		{
		p[i].mark=2;
		p[i].duizi[0]=p[i].s[1];
		p[i].duizi[1]=p[i].s[0]+p[i].s[3]+p[i].s[4]; 
		}
		 
		else if(p[i].s[2]==p[i].s[3])
		{
		p[i].mark=2;
		p[i].duizi[0]=p[i].s[2];
		p[i].duizi[1]=p[i].s[0]+p[i].s[1]+p[i].s[4]; 
		}

		else if(p[i].s[3]==p[i].s[4])
		{
		p[i].mark=2;
		p[i].duizi[0]=p[i].s[3];
		p[i].duizi[1]=p[i].s[0]+p[i].s[1]+p[i].s[2]; 
		}
		
		else
		{
		p[i].mark=1;
		p[i].dapai=p[i].s[0]+p[i].s[1]+p[i].s[2]+p[i].s[3]+p[i].s[4]; 
		}
		 


}


int main()
{

int n;
char pai[11];
int cnt=0; 
while(scanf("%d",&n)!=EOF)
{

for(int i=0;i<n;i++)
	{p[i].init();
	memset(pai,0,sizeof(pai));
	cin>>p[i].name>>pai;
	int length=strlen(pai);
	for(int l=0;l<length;l++)
		{if(pai[l]=='A')
			p[i].s[cnt]=1;
		else if(pai[l]=='J')
			p[i].s[cnt]=11;
		else if(pai[l]=='Q')
			p[i].s[cnt]=12;
		else if(pai[l]=='K')
			p[i].s[cnt]=13;
		else if(pai[l]=='1')
			{p[i].s[cnt]=10;
			l++;}
		else
			p[i].s[cnt]=int(pai[l]-'0');
		//cout<<p[i].s[cnt]<<endl;	
		cnt++;
		
		
		}
	
	cnt=0;
	}

for(int i=0;i<n;i++)
	judgetype(i);
	//cout<<"mark"<<p[i].mark<<endl;
	
	
sort(p,p+n,xiaoyu);

for(int i=n-1;i>=0;i--)
{	cout<<p[i].name<<endl;}
//	for(int m=0;m<5;m++)
//	cout<<p[i].s[m]<<" ";
//	cout<<endl;}
}}

C - 签到题

问题描述

SDUQD 旁边的滨海公园有 x 条长凳。第 i 个长凳上坐着 a_i 个人。这时候又有 y 个人将来到公园,他们将选择坐在某些公园中的长凳上,那么当这 y 个人坐下后,记k = 所有椅子上的人数的最大值,那么k可能的最大值mx和最小值mn分别是多少。

Input

第一行包含一个整数 x (1 <= x <= 100) 表示公园中长椅的数目
第二行包含一个整数 y (1 <= y <= 1000) 表示有 y 个人来到公园
接下来 x 个整数 a_i (1<=a_i<=100),表示初始时公园长椅上坐着的人数

Output

输出 mn 和 mx

Input Example

3
7
1
6
1

Output Example

6 13

解题思路

  • 对所有长椅根据人数排序,获得最大值,记为m
  • 设来了y人,则最大人数就是m+y;
  • 最小值
    • 因为当前最多人的长椅不会变少,所以最小值大于等于m;用y把每个长椅的人补到m,每次y减去用的人数,即使y变负;
    • y为负,则说明不够补到m,最大值为m
    • y为正,则说明补到m还有剩余,则把剩下的y-m个人尽可能的平均分即可。

完整代码

#include<iostream>
#include<algorithm>
#include<cstring>
using namespace std;
int a[1000]; 
int main()
{
int x,y;
cin>>x>>y;
int m=y;
for(int i=0;i<x;i++)
	cin>>a[i];
sort(a,a+x);
for(int i=0;i<x-1;i++)
{y=y-(a[x-1]-a[i]);}//把他们都补到当前最大值 
	
	if(y<0)//最大值就是原来的最大值 
cout<<a[x-1]<<" ";
	
	else//平均分
{
	int n=y/x;
	int left=y%x;
	if(left!=0)
		left=1;
	cout<<a[x-1]+n+left<<" ";
} 

cout<<a[x-1]+m<<endl;



}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值