解题思路:
整体来讲,这道题目是一道极其复杂的模拟题,反正是我见过的最复杂的一道了,不过这道题,助教在课堂上已经做了充分解释,详细的展示了其思维过程,尽管这样,自己在做的时候也是比较困难的,这道题我们是利用指针来进行处理的,自己感觉指针的一大好处是具有一定的记忆性功能,尤其体现在这道题目的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;
}
}
}在这里插入代码片