CCFCSP认证202012-3带配额的文件系统满分题解(C++)

#include<iostream>
#include<map>
#include<vector>
#include<regex>
#define max 2e+18

using namespace std;

typedef long long ll;

enum retype{
	notexist,isfile,iscata
};//next函数的返回枚举,分别表示文件不存在,文件为普通文件,文件为目录文件 

typedef struct files{
	int type;//文件类型,0目录文件,1普通文件 
	string name;
	ll ld=0,lr=0,sd=0,sr=0; 
	map<string,struct files>child;// key值string为文件夹下子文件名 
}file;



ll lrmin;//路径中lr产生的最小限额 

file root;//根目录 
file *nowcata;//指向当前正在被操作的文件夹 
vector<file* > cv;//记录路径用以回溯 


void init(){//每次操作时的初始化函数 
	lrmin=max;
	nowcata=&root;
	cv.clear();
}


bool setL(ll nld,ll nlr){//尝试对当前文件夹设置新的ld和lr 
	//cout<<nowcata->sd<<":"<<nowcata->sr<<endl;
	if((nld==0||nowcata->sd<=nld)&&(nlr==0||nowcata->sr<=nlr)){
		nowcata->ld=nld;
		nowcata->lr=nlr;
		return true;
	}else{
		return false;
	}
}

bool changeS(ll csd,ll csr){//尝试修改当前文件的sd和sr 
	if((nowcata->ld==0||nowcata->ld>=nowcata->sd+csd)&&(nowcata->lr==0||nowcata->lr>=nowcata->sr+csr)){
		nowcata->sd+=csd;		
		nowcata->sr+=csr;
		//cout<<nowcata->name<<":\tsd:"<<nowcata->sd<<"\tsr:"<<nowcata->sr<<endl;
		return true;
	}else{
		cout<<"flase"<<endl;
		return false;
	}
}


retype next(string s){//尝试进入名为s的子文件夹 
	if(nowcata->child.find(s)==nowcata->child.end()){
		return notexist;
	}else{
		if(nowcata->child[s].type==1){
			return isfile;
		}else{
			cv.push_back(nowcata);
			nowcata=&nowcata->child[s];
			if(nowcata->lr!=0&&nowcata->lr-nowcata->sr<lrmin){
				lrmin=nowcata->lr-nowcata->sr;//更新lrmin 
			}		
			return iscata;
		}
	}
}


bool back(){//尝试回到上一级文件夹 
	if(cv.empty()){
		return false;
	}else{
		auto it=cv.end();
		it--;
		nowcata=*it;
		cv.pop_back();
		return true;
	}
}



bool delect(string s){//尝试删除当前文件夹下名为s的文件,并修改所有上级文件夹的sr和sd; 
	retype re;
	ll fs;
	re=next(s);
	if(re==notexist){
		return false;	
	}else if(re==isfile){
		fs=nowcata->child[s].sr;
		nowcata->child.erase(s);
		nowcata->sd-=fs;
		nowcata->sr-=fs;
		while(back()){
			changeS(0,-fs);
		}
		return true;
	}else{
		back();
		fs=nowcata->child[s].sr;
		nowcata->child.erase(s);
		nowcata->sr-=fs;
		while(back()){
			changeS(0,-fs);
		}
		return true;
	}
}


bool CC(string s){//创建一个新的子文件夹 
	file node;
	node.name=s;
	node.type=0;
	nowcata->child.insert(make_pair(s,node));
	return true;
}


bool CF(string s,ll fs){//尝试在当前文件夹创建一个新的文件,或修改已存在的文件,最后修改所有上级文件夹的sr和sd; 
	retype re;
	re=next(s);
	ll xfs;
	file node;
	node.name=s;
	node.sd=fs;
	node.sr=fs;
	node.type=1;
	if(re==iscata){
		return false;
	}else if(re==isfile){
		xfs=fs-nowcata->child[s].sr;	
	}else{
		xfs=fs;	
	}
	if(xfs>lrmin||(nowcata->ld!=0&&nowcata->sd+xfs>nowcata->ld)){
		return false;
	}
	nowcata->child.insert(make_pair(s,node));
	nowcata->child[s].sr=fs;
	nowcata->child[s].sd=fs;
	changeS(xfs,xfs);
	while(back()){
		changeS(0,xfs);
	}
	return true;
}

vector<string> s2v(string s){//将路径以“/”分割为string向量返回; 
	vector<string> re;
	string ds="root";
	ds.append(s);
	regex reg("/");
	sregex_token_iterator pos(ds.cbegin(),ds.cend(),reg,-1);
	sregex_token_iterator end;
	for(;pos!=end;pos++){
		//cout<<pos->str()<<endl;
		re.push_back(pos->str());
	}
	return re;
}

bool Copp(string ds){//创建操作 
	ll fs;
	cin>>fs;
	init();
	vector<string> fp=s2v(ds);
	auto it=fp.end();
	it--;
	string f=*it;
	fp.pop_back();
	retype re;
	for(it=fp.begin();it!=fp.end();it++){
		re=next(*it);
		if(re==isfile){
			return false;		
		}else if(re==notexist){
			break;
		}else{
			continue;
		}
	}
	for(;it!=fp.end();it++){
		if(fs<=lrmin){
			CC(*it);
			next(*it);
		}else{
			return false;
		}
	}
	return CF(f,fs);
}

bool Ropp(string s){//删除操作 
	vector<string> fp=s2v(s);
	init();
	auto it=fp.end();
	it--;
	string f=*it;
	fp.pop_back();
	retype re;
	for(it=fp.begin();it!=fp.end();it++){
		re=next(*it);
		if(re==iscata){
			continue;
		}else{
			return true;
		}
	}
	delect(f);
	return true;
}

bool Qopp(string s){//修改配额操作 
	ll nld,nlr;
	cin>>nld>>nlr;
	init();
	vector<string> fp=s2v(s);
	auto it=fp.end();
	retype re;
	for(it=fp.begin();it!=fp.end();it++){
		re=next(*it);
		if(re==iscata){
			continue;
		}else{
			return false;
		}
	}
	return setL(nld,nlr);
}



int main(){
	int n;
	string t,ds;
	file node;
	node.name="root";
	node.type=0;
	root.child.insert(make_pair("root",node));
	cin>>n;
	for(int i=0;i<n;i++){
		cin>>t>>ds;//只读取操作符和路径 
		if(t=="C"){
			if(Copp(ds)){
				cout<<"Y"<<endl;
			}else{
				cout<<"N"<<endl;
			}
		}else if(t=="R"){
			Ropp(ds);
			cout<<"Y"<<endl;
		}else{
			if(Qopp(ds)){
				cout<<"Y"<<endl;
			}else{
				cout<<"N"<<endl;
			}
		}
	}
	
	return 0;
}

 

好好写过注释了,这题的问题不是在于难不难,而是代码要写的足够干净。一个小技巧是,创建文件时,我并没有回溯检查是否满足配额限制,而是在dfs的过程中记录当前lr-sr的最小值为lrmin,只要创建文件所增加的容量小于lrmin,即可创建成功。

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值