week9作业

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

解题思路:

整体来讲,这道题目是一道极其复杂的模拟题,反正是我见过的最复杂的一道了,不过这道题,助教在课堂上已经做了充分解释,详细的展示了其思维过程,尽管这样,自己在做的时候也是比较困难的,这道题我们是利用指针来进行处理的,自己感觉指针的一大好处是具有一定的记忆性功能,尤其体现在这道题目的undo操作上,因为指针在断开连接后其内在的连接关系还在,在这方面,其是有一定的优越性的。对于这道题而言,除了undo操作外,对于tree操作,也是比较难处理,因为其根据个数分的情况比较多,在这里我们需要对递归的思想比较熟悉,对于递归而言,二叉树的三种遍历是一个很好的体现,所以,我们在解决递归问题时,可以在脑海中形成一棵二叉树,模拟其操作过程,这样对于我们编写一些递归函数有很大的思维逻辑上的帮助。

#include<iostream>
#include<stdio.h>
#include<string>
#include<map>
#include<vector>
using namespace std;
char tmps[20];
struct directory {
    	string name; //当前目录;
		map<string,directory*> children;
		directory* parent;
		int subtreesize;
		vector<string>* tendescendants=new vector<string>;
		bool updated;
		directory(string name,directory* parent) {
			this->name=name;
			this->parent=parent;
			this->subtreesize=1;
		}
	public:
		bool addchild(directory* ch) {
			if(children.find(ch->name)!=children.end())
				return false;
			children[ch->name]=ch;
			maintain(+ch->subtreesize);
			return true;
		}
		directory* getchild(string name) {
			map<string,directory*>::iterator it=children.find(name);
			if(it==children.end())
				return NULL;
			return it->second;
		}
		directory* mkdir(string name) {
			if(children.find(name)!=children.end())
				return NULL;
			directory* ch=new directory(name,this);
			children[name]=ch;
			maintain(+1);
			return ch;
		}
		directory* rm(string  name) {
			map<string,directory*>::iterator it=children.find(name);
			if(it==children.end())
				return NULL;
			maintain(-1*it->second->subtreesize);
			children.erase(it);
			return it->second;
		}
		directory* cd(string name) {
			if(".."==name)
				return this->parent;
			return getchild(name);
		}
		void maintain(int delta) {
			updated=true;
			subtreesize+=delta;
			if(parent!=NULL)
				parent->maintain(delta);
		}
		void sz() {
			printf("%d\n",this->subtreesize);
		}
		void ls() {
			int sz=children.size();
			if(sz==0)printf("EMPTY\n");
			else if(sz<=10)
				for(map<string,directory*>::iterator it=children.begin(); it!=children.end(); it++)
					printf("%s\n",it->first.c_str());
			else {
				map<string,directory*>::iterator it=children.begin();
				for(int i=0; i<5; i++,it++)
					printf("%s\n",it->first.c_str());
				printf("...\n");
				it=children.end();
				for(int i=0; i<5; i++)it--;
				for(int i=0; i<5; i++,it++) {
					printf("%s\n",it->first.c_str());
				}
			}
		}
		void tree() {
			if(subtreesize==1)printf("EMPTY\n");
			else if(subtreesize<=10) {
				if(this->updated) {
					tendescendants->clear();
					treeAll(tendescendants);
					this->updated=false;
				}
				for(int i=0; i<subtreesize; i++)
					printf("%s\n",tendescendants->at(i).c_str());
			} else {
				if(this->updated) {
					tendescendants->clear();
					treefirst(5,tendescendants);
					treelast(5,tendescendants);
					this->updated=false;
				}
				for(int i=0; i<5; i++)
					printf("%s\n",tendescendants->at(i).c_str());
				printf("...\n");
				for(int i=9; i>=5; i--)
					printf("%s\n",tendescendants->at(i).c_str());
			}
		}
		void treeAll(vector<string>* bar)
		{
			bar->push_back(name);
			for(map<string,directory*>::iterator it=children.begin();it!=children.end();it++)
			{
				it->second->treeAll(bar);
			}
		}
		void treefirst(int num,vector<string>* bar)
		{
			bar->push_back(name);
			if(--num==0)return;
			int n=children.size();
			map<string,directory*>::iterator it=children.begin();
			while(n--)
			{
				int sts=it->second->subtreesize;
				if(sts>=num)
				{
					it->second->treefirst(num,bar);
					return;
				}
				else
				{
					it->second->treefirst(sts,bar);
					num-=sts;
				}
				it++;
			}	
		}
		void treelast(int num,vector<string>* bar)
		{
			int n=children.size();
			map<string,directory*>::iterator it=children.end();
			while(n--)
			{
				it--;
				int sts=it->second->subtreesize;
				if(sts>=num)
				{
					it->second->treelast(num,bar);
					return;
				}
				else
				{
					it->second->treelast(sts,bar);
					num-=sts;
				}
			}
			bar->push_back(name);
		}
};
struct command {
	const string cmd_names[7]= {"MKDIR","RM","CD","SZ","LS","TREE","UNDO"};
	int type;
	string arg;
	directory* tmpdir;
	command(string s) {
		for(int i=0; i<7; i++) {
			if(cmd_names[i]==s) {
				type=i;
				if(i<3) scanf("%s",tmps),arg=tmps;
				return;
			}
		}
	}
};
void solve() {
	int n;
	scanf("%d",&n);
	directory* now=new directory("root",nullptr);
	vector<command*> cmdlist;
	while(n--) {
		scanf("%s",tmps);
		command* cmd=new command(tmps);
		switch(cmd->type) {
			case 0: 
				cmd->tmpdir=now->mkdir(cmd->arg);
				if(cmd->tmpdir==NULL)printf("ERR\n");
				else {
					printf("OK\n");
					cmdlist.push_back(cmd);
				}
				break;
			case 1:
				cmd->tmpdir=now->rm(cmd->arg);
				if(cmd->tmpdir==NULL)printf("ERR\n");
				else {
					printf("OK\n");
					cmdlist.push_back(cmd);
				}
				break;
			case 2:
				{
					directory* ch=now->cd(cmd->arg);
					if(ch==NULL)printf("ERR\n");
					else {
						printf("OK\n");
						cmd->tmpdir=now;
						now=ch;
						cmdlist.push_back(cmd);
					}
					break;
				}	
			case 3:
				now->sz();
				break;
			case 4:
				now->ls();
				break;
			case 5:
				now->tree();
				break;
			case 6:
				bool success=false;
				if(!success&&!cmdlist.empty()) {
					cmd=cmdlist.back();
					cmdlist.pop_back();
					switch(cmd->type) {
						case 0:
							success=now->rm(cmd->arg)!=NULL;
							break;
						case 1:
							success=now->addchild(cmd->tmpdir);
							break;
						case 2:
							now=cmd->tmpdir;
							success=true;
							break;	
					}
				}
				printf(success?"OK\n":"ERR\n");
		}
	}
}
int main() {
	int T;
	scanf("%d",&T);
	while(T--) {
		solve();
	}
}在这里插入代码片

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 张牌不同,其值不同。下面依次列举了这手牌的形成规则:
大牌:这手牌不符合下面任一个形成规则。如果 α 和 β 都是大牌,那么定义它们的大小为组成这手牌的 5 张牌的大小总和。
对子:5 张牌中有 2 张牌的值相等。如果 α 和 β 都是对子,比较这个 “对子” 的大小,如果 α 和 β 的 “对子” 大小相等,那么比较剩下 3 张牌的总和。
两对:5 张牌中有两个不同的对子。如果 α 和 β 都是两对,先比较双方较大的那个对子,如果相等,再比较双方较小的那个对子,如果还相等,只能比较 5 张牌中的最后那张牌组不成对子的牌。
三个:5 张牌中有 3 张牌的值相等。如果 α 和 β 都是 “三个”,比较这个 “三个” 的大小,如果 α 和 β 的 “三个” 大小相等,那么比较剩下 2 张牌的总和。
三带二:5 张牌中有 3 张牌的值相等,另外 2 张牌值也相等。如果 α 和 β 都是 “三带二”,先比较它们的 “三个” 的大小,如果相等,再比较 “对子” 的大小。
炸弹:5 张牌中有 4 张牌的值相等。如果 α 和 β 都是 “炸弹”,比较 “炸弹” 的大小,如果相等,比较剩下那张牌的大小。
顺子:5 张牌中形成 x, x+1, x+2, x+3, x+4。如果 α 和 β 都是 “顺子”,直接比较两个顺子的最大值。
龙顺: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

解题思路:
对于这道题而言,其实在逻辑上并不难,属于那种看见能够有思路的题目,不过自己还是wa了很多次,而且错误点不止一个,这充分说明了自己在思维逻辑上还不够严谨,对于一些问题还存在想当然的情况,逻辑上的严谨性是我们迫切需要的,这对于一次AC的能力至关重要。
说一下这个题目,这个与我们之前写过的一道题目相似,起码思维上很像。整体的过程便是重载结构体的小于号,重新排序,但重载过程中是比较复杂的,整体的策略便是由高优先级向低优先级方向逐步思考,便是逐渐进行if判断的一个过程。不过,自己错的一个关键原因在于对于二者相等的情况没有考虑全面,其实这个在题头上已经明确说明了,这便属于审题不清,此类错误不应当犯。

#include<iostream>
#include<stdio.h>
#include<string.h>
#include<string>
#include<algorithm>
using namespace std;
struct Node {
	string name;
	int number[5];
	int type;
	bool operator<(const Node& p)const {
		if(number[0]==p.number[0]&&number[1]==p.number[1]&&number[2]==p.number[2]&&number[3]==p.number[3]&&number[4]==p.number[4]) {
			return name>p.name;
		} else {
			if(type<p.type)
				return true;
			else if(type>p.type)
				return false;
			else {
				if(type==1)
				    if(number[0]+number[1]+number[2]+number[3]+number[4]!=p.number[0]+p.number[1]+p.number[2]+p.number[3]+p.number[4])
					return number[0]+number[1]+number[2]+number[3]+number[4]<p.number[0]+p.number[1]+p.number[2]+p.number[3]+p.number[4];
					else
					return name>p.name;	
				else if(type==2) {
					int i,j;
					for(i=0; i<4; i++) {
						if(number[i]==number[i+1])
							break;
					}
					for(j=0; j<4; j++) {
						if(p.number[j]==p.number[j+1])
							break;
					}
					if(number[i]<p.number[j])
						return true;
					else if(number[i]>p.number[j])
						return false;
					else {
						int a=0,b=0;
						for(int k1=0; k1<=4; k1++) {
							if(number[k1]!=number[i])
								a+=number[k1];
						}
						for(int k2=0; k2<=4; k2++) {
							if(p.number[k2]!=p.number[j])
								b+=p.number[k2];
						}
						if(a!=b)
						return a<b;
						else
						return name>p.name;
					}
				} else if(type==3) {
					int a=number[3];
					int b=p.number[3];
					if(a<b)
						return true;
					else if(a>b)
						return false;
					else {
						int c=number[1];
						int d=p.number[1];
						if(c<d)
							return true;
						else if(c>d)
							return false;
						else {
							int i,j;
							for( i=0; i<5; i++) {
								if(number[i]!=a&&number[i]!=c)
									break;
							}
							for( j=0; j<5; j++) {
								if(p.number[j]!=b&&p.number[j]!=d)
									break;
							}
							if(number[i]!=p.number[j])
							return number[i]<p.number[j];
							else 
							return name>p.name;
						}
					}
				} else if(type==4) {
					int a=number[2];
					int b=p.number[2];
					if(a<b)
						return true;
					else if(a>b)
						return false;
					else {
						int c=0,d=0;
						for(int i=0; i<5; i++) {
							if(number[i]!=a)
								c+=number[i];
						}
						for(int j=0; j<5; j++) {
							if(p.number[j]!=b)
								d+=p.number[j];
						}
						if(c!=d)
						return c<d;
						else
						return name>p.name;
					}
				} else if(type==5) {
					int a=number[2];
					int b=p.number[2];
					if(a<b)
						return true;
					else if(a>b)
						return false;
					else {
						int c,d;
						for(int i=0; i<5; i++) {
							if(number[i]!=a) {
								c=number[i];
								break;
							}
						}
						for(int j=0; j<5; j++) {
							if(p.number[j]!=b) {
								d=p.number[j];
								break;
							}
						}
						if(c!=d)
						return c<d;
						else
						return name>p.name;
					}
				} else if(type==6) {
					if(number[1]<p.number[1])
						return true;
					else if(number[1]>p.number[1])
						return false;
					else {
						int a=0,b=0;
						if(number[0]==number[1])
							a=4;
						if(p.number[0]==p.number[1])
							b=4;
						if(number[a]!=p.number[b])
						return number[a]<p.number[b];
						else
						return name>p.name;
					}
				} else if(type==7) {
					if(number[4]!=p.number[4])
					return number[4]<p.number[4];
					else
					return name>p.name;
				}
			}
		}

	}

} node[100005];
int judge(int* t) {
	if(t[0]==1&&t[1]==10&&t[2]==11&&t[3]==12&&t[4]==13)
		return 8;
	if(t[0]+1==t[1]&&t[1]+1==t[2]&&t[2]+1==t[3]&&t[3]+1==t[4])
		return 7;
	if((t[0]==t[1]&&t[1]==t[2]&&t[2]==t[3])||(t[1]==t[2]&&t[2]==t[3]&&t[3]==t[4]))
		return 6;
	if((t[0]==t[1]&&t[1]==t[2]&&t[3]==t[4])||(t[2]==t[3]&&t[3]==t[4]&&t[1]==t[0]))
		return 5;
	if((t[0]==t[1]&&t[1]==t[2])||(t[3]==t[1]&&t[1]==t[2])||(t[3]==t[4]&&t[4]==t[2]))
		return 4;
	if((t[0]==t[1]&&t[2]==t[3])||(t[0]==t[1]&&t[3]==t[4])||(t[1]==t[2]&&t[3]==t[4]))
		return 3;
	if(t[0]==t[1]||t[1]==t[2]||t[2]==t[3]||t[3]==t[4])
		return 2;
	else
		return 1;
}
int func=0;
int label=0;
int main() {
	int n;
	while(scanf("%d",&n)!=EOF) {
		string s1,s2;
		func=0; 
		int t=n;
		while(t--) {
			cin>>s1>>s2;
			node[func].name=s1;
			int size=s2.size();
			label=0;
			for(int i=0; i<size; i++) {
				if(s2[i]=='A')
					node[func].number[label++]=1;
				else if(s2[i]=='J')
					node[func].number[label++]=11;
				else if(s2[i]=='Q')
					node[func].number[label++]=12;
				else if(s2[i]=='K')
					node[func].number[label++]=13;
				else if(s2[i]=='1') {
					node[func].number[label++]=10;
					i++;
				} else
					node[func].number[label++]=s2[i]-'0';
			}
			sort(node[func].number,node[func].number+5);
			node[func].type=judge(node[func].number);
			func++;
		}
		sort(node,node+n);
		for(int i=n-1; i>=0; i--) {
			cout<<node[i].name<<endl;
		}
	}

}在这里插入代码片
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值