CodeForces - 327D Block Tower (dfs)

题目链接:http://codeforces.com/problemset/problem/327/D

题意:给出图的行列n和m,还有一个图,由’.’和’#’组成,分别表示平地和坑,然后现在要在平地上建造东西,给出三种操作,建蓝色房子(可以住100人),建红色房子(可以住200人),摧毁房子,进行这3种操作有分别的要求,建蓝色房子,要求在平地上,建红色房子要求在平地上而且旁边要有一座蓝色房子,摧毁操作可以选择一处房子进行摧毁,摧毁后的地方变成平地。要求让你进行若干次数的操作,使得这一整块地上能住尽可能多的人。输出操作次数和每一次操作。

分析:拿到这道题先画一画,发现可以一直建蓝色房子,直到不能建的时候再建红色房子,然后再原路返回摧毁建成红色房子,这样就以一直满足红色房子的要求而建尽可能多的红房子。所以dfs搞起来。

下面是1Y的代码(牛*坏了,撑会儿腰.jpg):

#include<cstdio>
#include<cstring>
#include<string>
#include<sstream>
#include<iostream>
#include<set>
#include<map>
#include<queue>
#include<deque>
#include<vector>
#include<algorithm>
#include<cctype>
#include<math.h>
#include<stdlib.h>
#include<stack>
#include<ctime>
#define mst(a,b) memset(a,b,sizeof(a))
#define ALL(x) x.begin(),x.end()
#define INS(x) inserter(x,x.begin())
#define pii pair<int,int>
const int N = 1e9;
const int mod=(int)1e9+7;
const int INF=0x3f3f3f3f;
const long long LINF=(1LL<<62);
typedef long long LL;
//#define LOCAL
const double PI = acos(-1.0);
const int maxn=1e5+5;
using namespace std;

char s[505][505];
int ud[4] = {1,0,-1,0};
int lr[4] = {0,1,0,-1};
int n, m;

struct node
{
    int x, y;
    char oper;    //操作种类
    node (int x=0, int y=0, char oper=0):x(x),y(y),oper(oper){}
};

queue<node> st;  //这里用队列方便对后面的操作(路径)进行输出

bool judge(int x, int y){
    if(x<1||x>n||y<1||y>m||s[x][y]=='#') return false;
    else return true;
}

void dfs(int x, int y, int ix, int iy)   //x,y为当前的位置,ix,iy为起始位置
{
    if(x==ix&&y==iy){    //起点的时候就先建一座蓝色的房子
        node t1(x,y,'B');
        st.push(t1);
        s[x][y] = '#';   //把这个地方变成坑,相当于访问过
    }
    int is = 0;
    for(int i = 0; i < 4; i++){  //四个方向
        int dx = x+ud[i];
        int dy = y+lr[i];
        if(judge(dx,dy)){
            s[dx][dy] = '#';
            int sum = 0;
            for(int j = 0; j < 4; j++){   //检验下一个位置的四周是否能再进行操作,如果不能就直接进行建红房子的操作,而不需要建蓝再摧毁。
                int ddx = dx+ud[j];
                int ddy = dy+lr[j];
                if(!judge(ddx,ddy)) sum++;
                else break;
            }
            if(sum==4) {node v(dx,dy,'R'); st.push(v); continue;} //四个方向都有坑(墙),直接建红房子。
            node v(dx,dy,'B'); //建蓝色房子,把操作push进队列
            st.push(v);
            dfs(dx,dy,ix,iy);
        }
    }
    if(x!=ix||y!=iy){   //递归回来的时候进行摧毁,然后建红房子的操作,如果是起点的位置则不用进行操作。
        node t1(x,y,'D');
        node t2(x,y,'R');
        st.push(t1);
        st.push(t2);
    }
    return ;
}

int main()
{
#ifdef LOCAL
    freopen("test.txt", "r", stdin);
#endif // LOCAL
    //ios::sync_with_stdio(false);
    scanf("%d%d", &n, &m);
    getchar();
    for(int i = 1; i <= n; i++){
        for(int j = 1; j <= m; j++) s[i][j] = getchar();
        getchar();
    }
    for(int i = 1; i <= n; i++){
        for(int j = 1; j <= m; j++){
            if(s[i][j]=='.') dfs(i,j,i,j);
        }
    }
    printf("%d\n", st.size());
    while(!st.empty()){   //FIFO贼方便。
        node u = st.front(); st.pop();
        printf("%c %d %d\n", u.oper, u.x, u.y);
    }
    return 0;
}

做的出来怕是要归功于寒假刷的专题。
跟大佬的差距还是很大的,要继续加油!!(:з)∠)

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值