I - Fire Game[多项最短路+bfs]

I - Fire Game

题意大致是,两个人要放火烧草地,而那块地上有草地也有空地,
草地与草地之间火势蔓延需要1分钟,问最少几分钟能把草地烧完,或者烧不完。
烧完就输出时间,烧不完就输出impossible

脑洞:刚开始本来想先染色,因为染色能分出烧完不烧完情况。但是这样时间复杂度太高,而且只能直接打印出impossible的情况,就不太行。
然后就把两个事件都放在同一个队列之中处理,因为我们只记录两个人中最长的时间,所以某一个人多快破坏完,不管。而如果烧不完怎么办?我们烧掉一块就标记一块,最后的时候把标记数组和原图对比一下,看看草地是不是已经烧完了。
本题就给了10*10 的图。我们从中随便选两块地方出来作为起点开始烧,所以结果数为100C2 = 9900. 但没想到更好的办法去优化。。。

struct node {
    int x,y,step;
};

struct node arr[110];
char m[len][len];
int vis[len][len];
int dv[4][2] = {{1, 0},{-1, 0},{0, 1},{0, -1}};
int N,M,T,n = 0;
int ans;
int main(){
    cin >> T;
    int s = 1;
    while (T--) {
        cin >> N >> M;
        Init();
        for (int i=0; i<n; i++) {
            for (int j=i; j<n; j++){
                int L = bfs(arr[i], arr[j]);//最短路
                
                if (ans > L && judge()) ans = L;
            }
        }
        
        if (ans == MAXN) cout << "Case " << s << ": -1" << endl;
        else cout << "Case " << s << ": " << ans << endl;
        s ++;
    }
    
    return 0;
}
void Init(){
    memset(arr, 0, sizeof(arr));
    memset(m, '.', sizeof(m));
    
    n = 0;//一定要。。不然出现段错误
    ans = MAXN;
    read();
    
}
void read(){
    for (int i=0; i<N; i++){
        for (int j=0; j<M; j++){
            cin >> m[i][j];
            
            if (m[i][j] == '#'){//看到一个草地就存起来,入数组
                arr[n].x = i;
                arr[n].y = j;
                arr[n].step = 0;
                n++;
                
            }
        }
    }
}
bool judge()
{
    int i, j;
    
    for(i=0; i<N; i++){
        for(j=0; j<M; j++){
            if(m[i][j] == '#' && vis[i][j] == 0)//看看草地是不是被烧了
                return false;
        }
    }
    return true;
}
int bfs(struct node tmp1, struct node tmp2){
    queue <struct node> q;
    q.push(tmp1); q.push(tmp2);
    memset(vis, 0, sizeof(vis));
    vis[tmp1.x][tmp1.y] = vis[tmp2.x][tmp2.y] = 1;
    struct node head;
    while (!q.empty()) {

        head = q.front(); q.pop();
        
//        cout << head.x << " " << head.y << " " << head.step << endl;
        
        for (int i=0; i<4; i++){
            int _x = head.x + dv[i][0];
            int _y = head.y + dv[i][1];
            
             if (_x < 0 || _x >= N || _y < 0 || _y >= M) continue;
            if (vis[_x][_y]) continue;
            if (m[_x][_y] != '#') continue;
            
            struct node tmp;
            tmp.x = _x; tmp.y = _y; tmp.step = head.step + 1;
            q.push(tmp);
            vis[_x][_y] ++;
        }
    }
//    cout << endl;
    return head.step;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值