社区讨论

求助!70pts 下载本地fc与提交测试不符

P3693琪露诺的冰雪小屋参与者 1已保存回复 1

讨论操作

快速查看讨论及其快照的属性,并进行相关操作。

当前回复
1 条
当前快照
1 份
快照标识符
@los34ly7
此快照首次捕获于
2023/11/10 11:55
2 年前
此快照最后确认于
2023/11/10 16:05
2 年前
查看原帖
rt,代码见下,附数据点和测试情况。
CPP
#include<bits/stdc++.h>
using namespace std;
const int inf=1e6;
int n,m,hm,hr,hc,hx,hy,ice[100][100],block_cnt;
int block[100][100][100];
char opt[100];
void output_block_now(){
	for(int i=0;i<n;i++){
		for(int j=0;j<n;j++){
			for(int k=0;k<=hm;k++){
				if(block[i][j][k]==1){
					cout<<i<<' '<<j<<' '<<k<<endl;
				}
			}
		}
	}
}//调试用  
int check(){
	if(opt[1]=='I') return 1;
	if(opt[1]=='M'&&opt[6]=='I') return 2;
	if(opt[1]=='P') return 3;
	if(opt[1]=='R') return 4;
	return 5;
}//判断操作类型  
pair<int,int> getway(int d){
	if(d==0) return make_pair(-1,0);
	if(d==1) return make_pair(-1,-1);
	if(d==2) return make_pair(0,-1);
	if(d==3) return make_pair(1,-1);
	if(d==4) return make_pair(1,0);
	if(d==5) return make_pair(1,1);
	if(d==6) return make_pair(0,1);
	if(d==7) return make_pair(-1,1);
}//判断方向  
void do_ice_barrage(int r,int c,int d,int s){
	pair<int,int> way=getway(d);
	int cnt=0;
	for(int i=0;i<=s;i++){
		int tx=r+i*way.first;
		int ty=c+i*way.second;
		if(tx<0||tx>=n||ty<0||ty>=n) break;
		if(block[tx][ty][0]==1) break;
		if(ice[tx][ty]==4) continue;
		cnt++;
		ice[tx][ty]++;
	}
	printf("CIRNO FREEZED %d BLOCK(S)",cnt);
}//弹幕  
void do_make_ice_block(){
	int cnt=0;
	for(int i=0;i<n;i++){
		for(int j=0;j<n;j++){
			if(ice[i][j]==4){
				cnt++;
				ice[i][j]=0;
			}
		}
	}
	block_cnt+=cnt;
	printf("CIRNO MADE %d ICE BLOCK(S),NOW SHE HAS %d ICE BLOCK(S)\n",cnt,block_cnt);
}//铺冰砖  
bool check_block(int r,int c,int h){
	if(block[r][c][h]==1) return 0;
	if(h==0) return 1;
	if(block[r+1][c][h]==1||block[r-1][c][h]==1) return 1;
	if(block[r][c+1][h]==1||block[r][c-1][h]==1) return 1;
	if(block[r][c][h+1]==1||block[r][c][h-1]==1) return 1;
	return 0;
}//检查是否可以放置冰砖  
void do_put_ice_block(int r,int c,int h){
	if(!block_cnt){
		printf("CIRNO HAS NO ICE_BLOCK\n");
		return;
	}
	if(!check_block(r,c,h)){
		printf("BAKA CIRNO,CAN'T PUT HERE\n");
		return;
	}
	block[r][c][h]=1;
	if(h==0) ice[r][c]=0;
	block_cnt--;
	if(r<hr||r>hr+hx-1||c<hc||c>hc+hy-1)
		printf("CIRNO MISSED THE PLACE\n");
	else if(r>=hr+1&&r<=hr+hx-2&&c>=hc+1&&c<=hc+hy-2)
		printf("CIRNO PUT AN ICE_BLOCK INSIDE THE HOUSE\n");
	else printf("CIRNO SUCCESSFULLY PUT AN ICE_BLOCK,NOW SHE HAS %d ICE_BLOCK(S)\n",block_cnt);
}//放置冰砖  
int dx[6]={-1,1,0,0,0,0};
int dy[6]={0,0,-1,1,0,0};
int dz[6]={0,0,0,0,-1,1};//三向遍历  
bool vis[100][100][100];
int check_connection(int r,int c,int h){
	if(h==0) return -inf;
	vis[r][c][h]=1;
	int cnt=1;
	for(int i=0;i<6;i++){
		int tr=r+dx[i],tc=c+dy[i],th=h+dz[i];
		if(tr<0||tr>=n||tc<0||tc>=n||th<0||th>hm) continue;
		if(block[tr][tc][th]==0) continue;
		if(vis[tr][tc][th]) continue;
		cnt+=check_connection(tr,tc,th);
	}
	return cnt;
}//检查是否与地面连通 
void remove_connection(int r,int c,int h){
	block[r][c][h]=0;
	for(int i=0;i<6;i++){
		int tr=r+dx[i],tc=c+dy[i],th=h+dz[i];
		if(tr<0||tr>=n||tc<0||tc>=n||th<0||th>hm) continue;
		if(block[tr][tc][th]==0) continue;
		remove_connection(tr,tc,th);
	}
}//去除不联通的部分 
void do_remove_ice_block(int r,int c,int h){//移走冰块 
	if(block[r][c][h]==0){//没冰块 
		printf("BAKA CIRNO,THERE IS NO ICE_BLOCK\n");
		return;
	}
	block[r][c][h]=0;//先移走再判断其他位置  
	memset(vis,0,sizeof(vis));//初始化 
	int cnt=0;
	for(int i=0;i<6;i++){
		int tr=r+dx[i],tc=c+dy[i],th=h+dz[i];
		if(tr<0||tr>=n||tc<0||tc>=n||th<0||th>hm) continue;
		if(block[tr][tc][th]==0) continue;
		int now=check_connection(tr,tc,th);
		cnt+=max(0,now);
		if(now>0) remove_connection(tr,tc,th);
	}
	block_cnt++;//回收  
	if(cnt!=0)
		printf("CIRNO REMOVED AN ICE_BLOCK,AND %d BLOCK(S) ARE BROKEN\n",cnt);
	else
		printf("CIRNO REMOVED AN ICE_BLOCK\n");
}
pair<int,int>stu[10000];//存墙坐标 
int tot; 
int gethigher(pair<int,int>x){
	for(int i=hm;i>=0;i--)
		if(block[x.first][x.second][i]==1) return i;
	return -1;//获得高度  
}
int gethigh(){
	int res=-1;
	for(int i=1;i<=tot;i++)
		res=max(res,gethigher(stu[i]));
	return res;//获得墙壁最高位置  
}
int getcovery(int high){
	int cnt=0;
	for(int i=hr;i<=hr+hx-1;i++)
		for(int j=hc;j<=hc+hy-1;j++)
			if(block[i][j][high]==0) cnt++;
	return cnt;
}//获得屋顶所需方块  
void cover_block(int high){
	for(int i=hr;i<=hr+hx-1;i++)
		for(int j=hc;j<=hc+hy-1;j++)
			if(block[i][j][high]==0)
				block[i][j][high]=1;
	//填满屋顶  
}
bool flag[100][100][100];
int getinside(int high){
	int cnt=0;
	for(int i=hr+1;i<hr+hx-1;i++)
		for(int j=hc+1;j<hc+hy-1;j++)
			for(int k=0;k<=high;k++)
				if(block[i][j][k]==1) 
					cnt++,flag[i][j][k]=1;
	return cnt;
}
int getoutside(int high){
	int cnt=0;
	for(int i=0;i<n;i++)
		for(int j=0;j<n;j++)
			for(int k=0;k<=hm;k++)
				if(block[i][j][k]==1) 
					cnt++,flag[i][j][k]=1;  
	for(int i=hr;i<=hr+hx-1;i++)
		for(int j=hc;j<=hc+hy-1;j++)
			for(int k=0;k<=high+1;k++)
				if(block[i][j][k]==1) 
					cnt--,flag[i][j][k]=0;
	for(int i=hr+1;i<hr+hx-1;i++)
		for(int j=hc+1;j<hc+hy-1;j++)
			for(int k=0;k<=high;k++)
				if(block[i][j][k]==1) 
					flag[i][j][k]=1;
	return cnt;
}
void get_grand_connection(int r,int c,int h){
	vis[r][c][h]=1;
	flag[r][c][h]=1;
	for(int i=0;i<6;i++){
		int tr=r+dx[i],tc=c+dy[i],th=h+dz[i];
		if(tr<0||tr>=n||tc<0||tc>=n||th<0||th>hm) continue;
		if(block[tr][tc][th]==0) continue;
		if(vis[tr][tc][th]) continue;
		get_grand_connection(tr,tc,th);
	}
}
void try_remove_all_not_need(int high){
	for(int i=0;i<n;i++)
		for(int j=0;j<n;j++)
			for(int k=0;k<=hm;k++)
				if(flag[i][j][k]) 
					block[i][j][k]=0;
	memset(vis,0,sizeof(vis));
	memset(flag,0,sizeof(flag));
	for(int i=0;i<n;i++)
		for(int j=0;j<n;j++)
			if(!vis[i][j][0]&&block[i][j][0]==1)
				get_grand_connection(i,j,0);
	for(int i=0;i<n;i++)
		for(int j=0;j<n;j++)
			for(int k=0;k<=hm;k++)
				if(block[i][j][k]==1&&!flag[i][j][k]) 
					block[i][j][k]=-1;
}
bool wall_need;
int wall_need_cnt;
struct node{
	int val,corner,perfect,x,y;//三要素排顺序  
	bool door;
	//corner表示补上了几个拐角 冰砖相同的话越多越好  
}st[10000]; 
int top;
bool cmp(node a,node b){
	if(a.val!=b.val) return a.val<b.val;
	else{
		if(a.corner!=b.corner) return a.corner>b.corner;
		else return a.perfect>b.perfect;
	}
}		
bool door_need,door_perfect;	
pair<int,int>door_position;
void getdoor_wall_need(int high){
	for(int i=0;i<n;i++)
		for(int j=0;j<n;j++)
			for(int k=0;k<=hm;k++)
				if(block[i][j][k]==-1) 
					block[i][j][k]=1;//还原 不改变定性  
	int can_cnt=0;
	for(int i=hr;i<=hr+hx-1;i++){
		for(int j=hc;j<=hc+hy-1;j++){
			if(((i==hr)^(i==hr+hx-1)^(j==hc)^(j==hc+hy-1))==1){
				for(int k=0;k<=1;k++)
					if(block[i][j][k]==0) can_cnt++;//预处理  
				for(int k=2;k<=high;k++)
					if(block[i][j][k]==0) 
						wall_need_cnt++;
			}
		}
	}//门以上的先填了 不能填墙角  
	//开始考虑门怎么选 
	for(int i=hr;i<=hr+hx-1;i++){
		for(int j=hc;j<=hc+hy-1;j++){
			if(((i==hr)^(i==hr+hx-1)^(j==hc)^(j==hc+hy-1))==1){
				st[++top].x=i;
				st[top].y=j;
				st[top].val=can_cnt;//初始化 
				if(block[i][j][0]==0&&block[i][j][1]==0) st[top].door=0;
				else st[top].door=1;//是否需要挖开门  
				for(int k=0;k<=1;k++){
					if(block[i][j][k]==0) st[top].val--;//残缺变有用的  
				}//四个顶点 (hr,hc),(hr,hc+hy-1),(hr+hx-1,hc),(hr+hx-1,hc+hy-1) 
				if((i==hr&&j==hc+1)||(i==hr+1&&j==hc)){
					//开在左上角旁边  
					for(int k=0;k<=1;k++){
						if(block[hr][hc][k]==0&&block[i][j][k]==0) {
							st[top].val++;//多填一个冰砖  
							st[top].corner++;//多填一个拐角 
						}
					}
				}
				if((i==hr&&j==hc+hy-2)||(i==hr+1&&j==hc+hy-1)){
					//开在右上角旁边  
					for(int k=0;k<=1;k++){
						if(block[hr][hc+hy-1][k]==0&&block[i][j][k]==0) {
							st[top].val++;//多填一个冰砖  
							st[top].corner++;//多填一个拐角 
						}
					}
				}
				if((i==hr+hx-1&&j==hc+1)||(i==hr+hx-2&&j==hc)){
					//开在左下角旁边  
					for(int k=0;k<=1;k++){
						if(block[hr+hx-1][hc][k]==0&&block[i][j][k]==0) {
							st[top].val++;//多填一个冰砖  
							st[top].corner++;//多填一个拐角 
						}
					}
				}
				if((i==hr+hx-1&&j==hc+hy-2)||(i==hr+hx-2&&j==hc+hy-1)){
					//开在右下角旁边  
					for(int k=0;k<=1;k++){
						if(block[hr+hx-1][hc+hy-1][k]==0&&block[i][j][k]==0) {
							st[top].val++;//多填一个冰砖  
							st[top].corner++;//多填一个拐角 
						}
					}
				}
				if(i==hr+hx/2||i==hr+hx/2-(hx%2==0)||j==hc+hy/2||j==hc+hy/2-(hy%2==0))
					st[top].perfect=1;//是否完美无瑕  
			}
		}
	}
	sort(st+1,st+top+1,cmp);
	door_need=st[1].door;
	if(block[st[1].x][st[1].y][0]==1) block[st[1].x][st[1].y][0]=0,block_cnt++; 
	if(block[st[1].x][st[1].y][1]==1) block[st[1].x][st[1].y][1]=0,block_cnt++; 
	door_perfect=st[1].perfect;
	wall_need_cnt+=st[1].val;//算上最底下的要糊多少墙才够  
	door_position=make_pair(st[1].x,st[1].y);
	if(wall_need_cnt==0) wall_need=0;
	else wall_need=1;
}
void cover_door_wall(int high){ 
	for(int i=hr;i<=hr+hx-1;i++){
		for(int j=hc;j<=hc+hy-1;j++){
			if(((i==hr)^(i==hr+hx-1)^(j==hc)^(j==hc+hy-1))==1){
				for(int k=0;k<=1;k++)
					if(block[i][j][k]==0) 
						if(i!=door_position.first||j!=door_position.second)
							block[i][j][k]=1;
				for(int k=2;k<=high;k++)
					if(block[i][j][k]==0) 
						block[i][j][k]=1;
			}
		}
	}//糊墙 
	if(st[1].corner==0) return;//没拐角要特判 
	int i=door_position.first;
	int j=door_position.second;
	if((i==hr&&j==hc+1)||(i==hr+1&&j==hc))
		//开在左上角旁边  
		for(int k=0;k<=1;k++)
			if(block[hr][hc][k]==0) 
				block[hr][hc][k]=1;
	if((i==hr&&j==hc+hy-2)||(i==hr+1&&j==hc+hy-1))
		//开在右上角旁边  
		for(int k=0;k<=1;k++)
			if(block[hr][hc+hy-1][k]==0) 
				block[hr][hc+hy-1][k]=1;
	if((i==hr+hx-1&&j==hc+1)||(i==hr+hx-2&&j==hc))
		//开在左下角旁边  
		for(int k=0;k<=1;k++)
			if(block[hr+hx-1][hc][k]==0) 
				block[hr+hx-1][hc][k]=1;
	if((i==hr+hx-1&&j==hc+hy-2)||(i==hr+hx-2&&j==hc+hy-1))
		//开在右下角旁边  
		for(int k=0;k<=1;k++)
			if(block[hr+hx-1][hc+hy-1][k]==0) 
				block[hr+hx-1][hc+hy-1][k]=1;
}
int in,out,high;
void do_make_roof(){
	high=gethigh();//房顶高度为high+1 
	int covery=getcovery(high+1);
	if(covery>block_cnt){
		printf("SORRY CIRNO,NOT ENOUGH ICE_BLOCK(S) TO MAKE ROOF\n");
		exit(0);
	}
	if(high<1||hx<=2||hy<=2||(high==2&&hx==3&&hy==3)){
		printf("SORRY CIRNO,HOUSE IS TOO SMALL\n");
		exit(0);
	}
	block_cnt-=covery;
	cover_block(high+1);
	in=getinside(high);
	out=getoutside(high);
	printf("%d ICE_BLOCK(S) INSIDE THE HOUSE NEED TO BE REMOVED\n",in);
	printf("%d ICE_BLOCK(S) OUTSIDE THE HOUSE NEED TO BE REMOVED\n",out);
	try_remove_all_not_need(high);
	for(int i=hr;i<=hr+hx-1;i++){
		for(int j=hc;j<=hc+hy-1;j++){
			if(block[i][j][high+1]==-1){
				printf("SORRY CIRNO,HOUSE IS BROKEN WHEN REMOVING BLOCKS\n");
				exit(0);
			}
		}
	}
	block_cnt+=in+out;
	getdoor_wall_need(high);
	if(wall_need_cnt>block_cnt){
		printf("SORRY CIRNO,NOT ENOUGH ICE_BLOCKS TO FIX THE WALL\n");
		exit(0);
	}
	cover_door_wall(high);
	block_cnt-=wall_need_cnt;
}
bool corner_need;
void do_check_corner(){
	int cnt=0;
	for(int k=0;k<=high;k++){
		if(block[hr][hc][k]==0) cnt++;
		if(block[hr][hc+hy-1][k]==0) cnt++;
		if(block[hr+hx-1][hc][k]==0) cnt++;
		if(block[hr+hx-1][hc+hy-1][k]==0) cnt++;
	}
	if(cnt==0) corner_need=0;
	else corner_need=1;
}
void check_corner(){
	int cnt=0;
	for(int k=0;k<=high+1;k++){
		if(block[hr][hc][k]==0) cnt++;
		if(block[hr][hc+hy-1][k]==0) cnt++;
		if(block[hr+hx-1][hc][k]==0) cnt++;
		if(block[hr+hx-1][hc+hy-1][k]==0) cnt++;
	}
	if(cnt==0) 
		printf("\nCORNER IS OK");
	else{
		printf("\nCORNER NEED TO BE FIXED");
		block_cnt=max(block_cnt-cnt,0);
	}
}
void do_check_end(){
	printf("GOOD JOB CIRNO,SUCCESSFULLY BUILT THE HOUSE");
	if(door_need)
		printf("\nHOUSE HAS NO DOOR");
	else printf("\nDOOR IS OK");
	if(wall_need)
		printf("\nWALL NEED TO BE FIXED");
	else printf("\nWALL IS OK");
	check_corner();
	printf("\nCIRNO FINALLY HAS %d ICE_BLOCK(S)",block_cnt);
	if(wall_need==0&&in==0&&out==0&&door_need==0&&corner_need==0&&door_perfect==1)
		printf("\nCIRNO IS PERFECT!");
}
void init(){
	for(int i=hr;i<=hr+hx-1;i++)
		for(int j=hc;j<=hc+hy-1;j++)
			if(i==hr||i==hr+hx-1||j==hc||j==hc+hy-1)
				stu[++tot]=make_pair(i,j);//预处理墙壁坐标  
} 
void work(){
	init();
	for(int i=1,r,c,d,S,h;i<=m;i++){
		scanf("%s",opt+1);
		int s=check();
		if(s==1){
			scanf("%d%d%d%d",&r,&c,&d,&S);
			do_ice_barrage(r,c,d,S);
			if(i!=m) printf("\n");
		}
		if(s==2)
			do_make_ice_block();
		if(s==3){
			scanf("%d%d%d",&r,&c,&h);
			do_put_ice_block(r,c,h);
		}
		if(s==4){
			scanf("%d%d%d",&r,&c,&h);
			do_remove_ice_block(r,c,h);
		}
		if(s==5){
			do_check_corner();
			do_make_roof();
			do_check_end();
		}
	}
//	output_block_now();
}
void input(){
//	freopen("P3693_18.in","r",stdin);
//	freopen("P3693_18.ans","w",stdout);
	scanf("%d",&n);
	scanf("%d",&hm);
	scanf("%d%d%d%d",&hr,&hc,&hx,&hy);
	scanf("%d",&m);
}
int main(){
	input();
	work();
	return 0;	
}

回复

1 条回复,欢迎继续交流。

正在加载回复...