Dragon slayer

https://acm.hdu.edu.cn/showproblem.php?pid=7139
这道题写了快4个小时,一开始看错题浪费了一个多小时,然后重做又一堆bug,生生要把人气死。写个题解记录一下。

题目描述

image
image

解题思路

注意到n,m,k的范围非常小,那么可以操作的空间就比较大。
一开始以为是最短路,但是每次运用能力可以消去一整堵强很不好处理,用最短路没法做。
于是考虑枚举,2的15次方大约在3e4左右。枚举所有剩余墙的组合,然后运用bfs判断英雄能否到达龙的位置就行了。最后取一个剩余墙最多,也就是运用能力次数最少的作为答案。
bfs大概复杂度在O(n*m),再乘个3e4,应该不会T。

代码

感觉自己的代码写的有点乱糟,不然也不会调了这么多次bug。。

#include <bits/stdc++.h>
using namespace std;

#define int long long

int mod = 1e9 + 7;

int n,m,K;

struct wall
{
    int x1,x2,y1,y2;
} w[20];     //作为墙的输入

bool ileg(int x,int y)
{
    if(x<0||x>=n||y<0||y>=m)
        return true;
    return false;
}
int dx[4] = {0,1,0,-1};
int dy[4] = {1,0,-1,0};

signed main()
{
    ios::sync_with_stdio(false);
    cin.tie(0);cout.tie(0);

    int xs,ys,xt,yt;

    int t;cin >> t;
    while(t--)
    {
        int ans = -1;    //记录最大剩余墙个数
        cin >> n >> m >> K;
        cin >> xs >> ys >> xt >> yt;
        for(int i=0;i<K;++i)
            cin >> w[i].x1 >> w[i].y1 >> w[i].x2 >> w[i].y2;
        for(int M=0;M<(1<<K);++M)    //枚举所有情况
        {
            //cout << 1 << endl;
            int tmp = 0;   //记录剩余墙的个数
            set<pair<int,int>> shu[16];   //竖着的墙
            set<pair<int,int>> heng[16];  //横着的墙
            for(int i=0;i<=K;++i)
            {
                if((1<<i)&M){    //墙被选中了
                    tmp++;
                    if(w[i].x1==w[i].x2)
                    {
                        shu[w[i].x1].insert({min(w[i].y1,w[i].y2),max(w[i].y1,w[i].y2)});
                    }
                    else{
                        heng[w[i].y1].insert({min(w[i].x1,w[i].x2),max(w[i].x1,w[i].x2)});
                    }
                }
            }
            //cout << "M " << M << endl;
            bool ok = 0;    //此情况是否合法

			//下面是bfs
            bool vis[16][16];
            memset(vis,0,sizeof vis);

            queue<pair<int,int>> q;
            q.push({xs,ys});
            vis[xs][ys] = 1;
            while(!q.empty())
            {
                pair<int,int> p = q.front();
                q.pop();
                //cout << p.first << " " << p.second << endl;

                if(p.first==xt&&p.second==yt)
                {
                    ok=1;
                    break;
                }

                for(int i=0;i<4;++i)
                {
                    int x = p.first + dx[i];
                    int y = p.second + dy[i];
                    if(ileg(x,y)) continue;
                    if(vis[x][y]) continue;
                    bool tiao = 0;
                    if(p.second==y)   //横着走是否有墙
                    {
                        int xx = x > p.first ? x : p.first;
                        if(!shu[xx].empty()){
                            for(auto l : shu[xx])
                                if(y>=l.first&&y<l.second)
                            {
                                tiao = 1;
                                break;
                            }
                        }
                        if(tiao) continue;
                    }
                    if(p.first==x)   //竖着走
                    {
                        int yy = y > p.second ? y : p.second;
                        if(!heng[yy].empty()){
                            for(auto l : heng[yy])
                                if(x>=l.first&&x<l.second)
                            {
                                tiao = 1;
                                break;
                            }
                        }
                        if(tiao) continue;
                    }
                    q.push({x,y});
                    vis[x][y] = 1;
                }
            }

            if(ok) ans = max(ans, tmp);
            //cout << ans << endl;
        }
        if(ans==-1) cout << -1 << endl;
        else cout << K - ans << endl;   //结果
    }

    return 0;
}
/*
3 2 2
2 1 0 0
0 1 3 1
1 0 1 2
*/

posted @ 2022-07-19 17:28  HIVM  阅读(85)  评论(0编辑  收藏  举报