社区讨论
求助!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 条回复,欢迎继续交流。
正在加载回复...