问题A - 咕咕东的目录管理器
问题描述
题目分析
这个题目主要的难点在于设计结构体,如何来表示这个文件以及文件下面的子文件。
在这个地方创建了一个结构体,里面包含了map和vector,int,string,bool多种结构。分别用以记录当前文件的各种信息,文件名,父文件地址,子文件和其对应的编号。
然后再用各个子函数来分开各个操作的处理方式。
建立文件,就是增加当前的map并将最后一个存放有文件信息的下一个 结构体,赋予其新的值,名字和大小,并更新所有的大小。
移动,只需要改变now这个数,将其变化为想要去的文件的地址。
删除文件,就是将now地址里的map删掉即可。
其余的显示结构,则是利用map对应的将其放进对应的vector中,再利用dfs遍历即可。
主要难得是撤回操作,撤回操作对应的上述三个操作都能够进行撤回,所以就要根据这三个专门写一个结构体来储存操作是什么,根目录和操作的目录的地址。但是由于要注意连续撤回的存在,所以不能只存一次的操作,要吧每一次的操作都存下来,于是又加上了一个vector来存放,每次去最后一个操作,将其还原。
代码
#include<iostream>
#include<map>
#include<vector>
#include<iterator>
#include <string>
using namespace std;
int T,Q;
struct mulu
{
string name;//名字
int pre;//父节点位置
map<string,int> child;//子树编号和其名字
int size;//大小
vector<string> pp,bb;//前5 后5
bool pan;//是否更新
};
mulu menu[200001];
int now,tot;
struct node//操作的储存
{
string name;
int now;
int next;
};
vector<node> mm;
void update(int id,int num) //更新目录大小
{
while(id!=-1)
{
menu[id].pan=false;
menu[id].size+=num;
id=menu[id].pre;
}
}
void MKDIR(string name)
{
if(menu[now].child.count(name)==1)
{
printf("ERR\n");
return;
}
else
{
//menu[now].child.insert(pair<string,int>());
menu[now].child[name]=tot;
update(now,1);
//cout<<"这个文件夹下的大小"<<menu[now].size<<endl;
menu[tot].name=name;
menu[tot].pre=now;
menu[tot].size=1;
menu[tot].pan=false;
menu[tot].child.clear();
menu[tot].pp.clear();
menu[tot].bb.clear();
//操作放入操作集合中
node thenode;
thenode.name="MKDIR";
thenode.now=now;
thenode.next=tot;
mm.push_back(thenode);
tot++;
printf("OK\n");
//cout<<"创建的有 "<<now<<endl;
//for(map<string,int>::iterator it=menu[now].child.begin();it!=menu[now].child.end();it++)
// cout<<it->first<<" ";
}
}
void RM(string name)
{
if(menu[now].child.count(name)==1)//||menu[wei].child[name]==-1
{
int x=menu[now].child[name];
update(now,-1*menu[x].size);
menu[now].child.erase(name);
node thenode;
thenode.name="RM";
thenode.now=now;
thenode.next=x;
mm.push_back(thenode);
printf("OK\n");
return;
}
else printf("ERR\n");
}
void CD(string &name)
{
if(name=="..")
{
//cout<<" 尝试 "<<name<<endl;
if(menu[now].pre==-1)
{
printf("ERR\n");
return;
}
node thenode;
thenode.name="CD";
thenode.now=now;
thenode.next=menu[now].pre;
mm.push_back(thenode);
now=menu[now].pre;
printf("OK\n");
return;
}
else
{
if(menu[now].child.count(name)==1)
{
node thenode;
thenode.name="CD";
thenode.now=now;
thenode.next=menu[now].child[name];
mm.push_back(thenode);
now=menu[now].child[name];
printf("OK\n");
return;
}
//cout<<"查询的名字 "<<name<<endl;
//for(map<string,int>::iterator it=menu[now].child.begin();it!=menu[now].child.end();it++)
// cout<<it->first<<" ";
printf("ERR\n");
}
}
void SZ()
{
printf("%d\n",menu[now].size);
}
void LS()
{
if(menu[now].child.size()==0)
{
printf("EMPTY\n");
return;
}
map<string,int>::iterator it;
if(menu[now].child.size()>=1&&menu[now].child.size()<=10)
{
for(it=menu[now].child.begin(); it!=menu[now].child.end(); it++)
cout<<it->first<<endl;
//printf("%s\n",it);//加上fisrt无法编译
//cout<<it->first<<endl;
return;
}
it=menu[now].child.begin();
for(int i=1;i<=5;i++)
{
cout<<it->first<<endl;
it++;
}
cout<<"..."<<endl;
it=menu[now].child.end();
for(int i=1;i<=5;i++)
it--;
for(int i=1;i<=5;i++)
{
cout<<it->first<<endl;
it++;
}
}
void quan(int id,vector<string> &pre)
{
pre.push_back(menu[id].name);
for(map<string,int>::iterator it=menu[id].child.begin();it!=menu[id].child.end();it++)
quan(it->second,pre);
}
void pp_track(int id,vector<string>& pre,int num)
{
pre.push_back(menu[id].name);
num--;
if(num==0)
return;
for(map<string,int>::iterator it=menu[id].child.begin();it!=menu[id].child.end();it++)
{
pp_track(it->second,pre,num);
if(num==0) break;
}
}
void bb_track(int id,vector<string>& bck,int num)
{
map<string,int>::iterator it=menu[id].child.end();
int n=menu[id].child.size();
for(int i=0;i<n;i++)
{
it--;
bb_track(it->second,bck,num);
if(num==0)return;
}
bck.push_back(menu[id].name);
num--;
}
void dfs(int n)
{
menu[n].bb.clear();
menu[n].pp.clear();
if(menu[n].size<=10)
quan(n,menu[n].pp);
else
{
pp_track(n,menu[n].pp,5);
bb_track(n,menu[n].bb,5);
}
menu[n].pan=true;
}
void TREE()
{
map<string,int>::iterator it;
//cout<<"树结构"<<endl;
//cout<<menu[now].name<<endl;
if(!menu[now].pan)//没有遍历过
dfs(now);
if(menu[now].size==1)
{
cout<<"EMPTY"<<endl;
}
else if(menu[now].size>=1&&menu[now].size<=10)
{
for(int i=0;i<menu[now].pp.size();i++)
cout<<menu[now].pp[i]<<endl;
//printf("%s\n",it);//加上fisrt无法编译
//cout<<it->first<<endl;
return;
}
else
{
for(int i=0;i<5;i++)
cout<<menu[now].pp[i]<<endl;
cout<<"..."<<endl;
for(int i=4;i>=0;i--)
cout<<menu[now].bb[i]<<endl;
}
}
void UNDO()
{
if(mm.size()==0)
{
printf("ERR\n");
return ;
}
node thenode;
thenode=mm[mm.size()-1];
mm.pop_back();
printf("OK\n");
//cout<<"上一个操作是:"<<thenode.name<<endl;
if(thenode.name=="MKDIR")
{
update(thenode.now,-1*menu[thenode.next].size);
menu[thenode.now].child.erase(menu[thenode.next].name);
}
else if(thenode.name=="RM")
{
update(thenode.now,menu[thenode.next].size);
menu[thenode.now].child[menu[thenode.next].name]=thenode.next;
}
else if(thenode.name=="CD")
{
now=thenode.now;
}
}
int main()
{
string name;
string op;
scanf("%d",&T);
for(int ti=0;ti<T;ti++)
{
scanf("%d",&Q);
now=0;tot=1;
menu[0].name="root";
menu[0].pre=-1;
menu[0].size=1;
menu[0].pan=false;
menu[0].child.clear();
menu[0].bb.clear();
menu[0].pp.clear();
mm.clear();
for(int qi=0;qi<Q;qi++)
{
//scanf("%s",&op);
cin>>op;
//cout<<endl<<op<<endl;
if(op=="MKDIR")
{
cin>>name;
MKDIR(name);
}
if(op=="RM")
{
cin>>name;
//scanf("%s",&name);
RM(name);
}
if(op=="CD")
{
cin>>name;
//scanf("%s",&name);
CD(name);
}
if(op=="SZ")
{
SZ();
}
if(op=="LS")
{
LS();
}
if(op=="TREE")
{
TREE();
}
if(op=="UNDO")
{
UNDO();
}
}
}
return 0;
}
遇到的问题
主要的问题就是对于stl的不熟悉,比如string和char弄混输入的问题。还有map的具体操作弄混也导致了一定程度的拖延了调试代码的进度
问题B - 东东学打牌
问题描述
题目分析
主要需要做的是重载符号小于,方便排序;
建立一个结构体,将需要的信息放进去,玩家的名字,玩家的牌,将牌转化为数字,然后看每个大小的牌有几个,对于mark,tot,和对应的数组(是几个一样的牌,以及那个牌是什么)。
在比较时,先比较mark,它表示目前是哪一种类型的牌,不同类型的牌完全不一样的大小。
如果mrak不一样,那么直接是谁的mark大谁就是大牌。
mark一样的情况下,就挨个比较,两对子的情况就从大往小比较对子的大小,根据具体的mark而定情况。
将char的牌转化为数字,利用了一个tmp数组,然后循环辨认char字符串,‘2’-’9‘分别对应1-9数字,‘A’-1,‘J’-11,‘Q’-12,‘K’-13,‘1’-10;使得对应的tmp[i]++,即确定该牌的个数。
在从后往前遍历tmp数组,看这手牌里有什么样数目的牌,存进结构体中,并对mark进行赋值。
从后往前是为了保证两个对子的时候,第一个一定是这两个中较大的那个对子。
代码
#include<iostream>
using namespace std;
#include<cstdio>
#include<cstring>
#include<algorithm>
struct node
{
char name[12];
char shu[12];
int mark;
int tot;
int two[3];
//0,是否有对;1,第一对是什么,2,第二对是什么
int three[2];
int four[2];
bool shun;
bool operator<(const node p)const
{
if(mark!=p.mark)
return mark>p.mark;
else if(mark==p.mark)
{
if(mark==1)
{
if(tot!=p.tot)
return tot>p.tot;
}
else if(mark==2)
{
if(two[1]!=p.two[1])
{
return two[1]>p.two[1];
}
else if(tot!=p.tot)
{
return tot>p.tot;
}
}
else if(mark==3)
{
if(two[1]!=p.two[1])
return two[1]>p.two[1];
else if(two[2]!=p.two[2])
return two[2]>p.two[2];
else if(tot!=p.tot)
return tot>p.tot;
}
else if(mark==4||mark==5)
{
if(three[1]!=p.three[1])
return three[1]>p.three[1];
else if(tot!=p.tot)
return tot>p.tot;
}
else if(mark==6)
{
if(four[1]!=p.four[1])
return four[1]>p.four[1];
else if(tot!=p.tot)
return tot>p.tot;
}
else if(mark==7)
{
if(tot!=p.tot)
return tot>p.tot;
}
}
int l1=strlen(name);
int l2=strlen(p.name);
for(int j=0;j<min(l1,l2);j++)
{
if(name[j]==p.name[j]) continue;
if(name[j]<p.name[j]) return true;
if(name[j]>p.name[j] ) return false;
}
if(l1<l2) return true;
else return false;
}
} a[100005];
int tmp[15];
void pre_function(int x)
{
int i=0;
memset(tmp,0,sizeof(tmp));
while(i<strlen(a[x].shu))
{
if(a[x].shu[i]=='1')
{
tmp[10]++;
i++;
}
else
{
if(a[x].shu[i]>='2'&&a[x].shu[i]<='9')
tmp[a[x].shu[i]-'0']++;
else
{
if(a[x].shu[i]=='A')
tmp[1]++;
if(a[x].shu[i]=='J')
tmp[11]++;
if(a[x].shu[i]=='Q')
tmp[12]++;
if(a[x].shu[i]=='K')
tmp[13]++;
}
}
i++;
}
if(tmp[1]&&tmp[10]&&tmp[11]&&tmp[12]&&tmp[13])
{
a[x].mark=8;
return;
}
for(int i=1;i<=13;i++)
{
if(tmp[i])
{
for(int j=1;j<=tmp[i];j++)
a[x].tot+=i;
}
}
for(int i=13;i>=1;i--)
{
if(tmp[i]==4)
{
a[x].four[0]=1;
a[x].four[1]=i;
a[x].mark=6;
return;
}
if(tmp[i]==3)
{
a[x].three[0]=1;
a[x].three[1]=i;
}
if(tmp[i]==2)
{
a[x].two[0]++;
if(a[x].two[0]==1)
a[x].two[1]=i;
else
{
a[x].two[2]=i;
a[x].mark=3;
return;
}
}
}
for(int i=1;i<=9;i++)
if(tmp[i]&&tmp[i+1]&&tmp[i+2]&&tmp[i+3]&&tmp[i+4])
{
a[x].shun=1;
a[x].mark=7;
return;
}
if(a[x].two[0]==1&&a[x].three[0]==1)
{
a[x].mark=5;
return;
}
if(a[x].two[0]==1)
{
a[x].mark=2;
return;
}
if(a[x].three[0]==1)
{
a[x].mark=4;
return;
}
a[x].mark=1;
}
void init(int x)
{
memset(a[x].two,0,sizeof(a[x].two));
memset(a[x].three,0,sizeof(a[x].three));
memset(a[x].four,0,sizeof(a[x].four));
a[x].shun=0;a[x].mark=0;a[x].tot=0;
}
int main()
{
int n;
while(scanf("%d",&n)!=EOF)
{
//cout<<"n="<<n<<endl;
for(int n1=1;n1<=n;n1++)
{
init(n1);
cin>>a[n1].name>>a[n1].shu;
pre_function(n1);
//scanf("%s",&nodes[n1].name);
//getchar();
//cout<<nodes[n1].name<<endl;
//scanf("%[^\n]",&nodes[n1].shu);
//getchar();
//cout<<nodes[n1].name<<" "<<nodes[n1].shu<<endl;
}
sort(a+1,a+n+1);
for(int i=1;i<=n;i++)
cout<<a[i].name<<endl;
}
}
遇到的问题
mark值的确定,尤其是3+2和3个的区别