UVA 10798 Be wary of Roses (BFS+几何状态对称)*

题目链接:https://cn.vjudge.net/problem/UVA-10798

#include<bits/stdc++.h>
#pragma comment(linker,"/STACK:1024000000,1024000000")
using namespace std;

#define debug puts("YES");
#define rep(x,y,z) for(int (x)=(y);(x)<(z);(x)++)
#define read(x,y) scanf("%d%d",&x,&y)

#define lrt int l,int r,int rt
#define lson l,mid,rt<<1
#define rson mid+1,r,rt<<1|1
#define ll long long
const int  maxn =25;
const int mod=1e9+7;
ll powmod(ll x,ll y) {ll t;for(t=1;y;y>>=1,x=x*x%mod) if(y&1) t=t*x%mod;return t;}
ll gcd(ll x,ll y)  {  return y==0?x:gcd(y,x%y); }
///head
/*
题目大意:这道题目意思很关键,
就是说路径必须是要唯一的,
我开始时读的以为是每个方向最小值取最大即可,
其实并不是。。。找一条唯一的路径,使得不论哪个方向踩的花数的最大值最小,
首先肯定用优先队列来看扩展节点,从权重最小的开始能保证找到最优解,
其次就是状态的问题了,由于几何对称性,
可以用状态数组唯一的标识,一条路径在所有方向产生的权重,
(注意,最多也就是边长,数组范围没有越界)。
这样一分析,问题就变成了普通的最短路BFS了。

*/
struct node
{
    int x,y;
    int l,r,u,d;
    int w;
    node(int tx=0,int ty=0,int tl=0,int tu=0,int tr=0,int td=0)
    {
        x=tx,y=ty;
        l=tl,r=tr,u=tu,d=td;
        w=max(max(l,r),max(u,d));
    }
    bool operator<(const node & y) const
    {
        return w>y.w;///最小堆
    }
};

int n;
int vis[maxn][maxn][maxn][maxn][maxn][maxn];
int mp[maxn][maxn];
char s[maxn];

int d1[]={0,0,1,-1};
int d2[]={1,-1,0,0};

int bfs(int x)
{
    memset(vis,0,sizeof(vis));
    priority_queue<node> pq;
    pq.push(node(x,x,0,0,0,0));
    vis[x][x][0][0][0][0]=1;
    while(!pq.empty())
    {
        node tp=pq.top();pq.pop();
        for(int i=0;i<4;i++)
        {
            node s=tp;
            int tx=s.x+d1[i];
            int ty=s.y+d2[i];
            if(tx<=0||tx>n||ty<=0||ty>n) return tp.w;

            s.x=tx;
            s.y=ty;

            if(mp[tx][ty]) s.l++;
            if(mp[ty][n-tx+1]) s.u++;
            if(mp[n-tx+1][n-ty+1]) s.r++;
            if(mp[n-ty+1][tx]) s.d++;
            if(vis[tx][ty][s.l][s.u][s.r][s.d]) continue;
            vis[tx][ty][s.l][s.u][s.r][s.d]=1;
            pq.push(node(s.x,s.y,s.l,s.u,s.r,s.d));
        }
    }
    return -1;
}


int main()
{
    while(scanf("%d",&n)&&n)
    {
        for(int i=1;i<=n;i++)
        {
            scanf("%s",s+1);
            for(int j=1;j<=n;j++)
                if(s[j]=='R') mp[i][j]=1;
                else mp[i][j]=0;
        }
        printf("At most %d rose(s) trampled.\n", bfs(n/2+1));
    }
    return 0;
}

猜你喜欢

转载自blog.csdn.net/qq_37451344/article/details/82525903