Hdu 6771 It‘s All Squares —— 暴力,矩阵上找被包含在多边形区域内的方法

This way

题意:

现在有一个n*m的矩形,每条边都是一条路,每个1*1的矩形的正中央有一个数字。每次给你起始点(在边上)一个包含L,R,U,D的字符串,表示走的方向,最终你走的会是一个简单多边形。问你被多边形包含的所有数字有多少个不同的。

题解:

这道题有两个点:
1.首先是选择的算法,假设每次都是暴力地遍历所有在多边形内的点,每次最多的时间复杂度是n*m,然后对于字符串长度最少需求是2*n+2*m,那么4e6的字符串最多让我们遍历4e6/400/4=2500次整个矩形。也就是最大的时间复杂度是2500*400*400=4e8.正好
2.已经知道了是暴力,那么怎么找哪些点是被包含的,解法五花八门,但是有一种容易被人忽略并且非常简单的方法:
保存每列的所有出现的行,按照位置从小到大排序之后,矩阵中第i~i+1(i是奇数)的那些数是被包含的:
Hdu 6771 It‘s All Squares —— 暴力,矩阵上找被包含在多边形区域内的方法_第1张图片
=>
Hdu 6771 It‘s All Squares —— 暴力,矩阵上找被包含在多边形区域内的方法_第2张图片
红色的就是入边,蓝色的就是出边,每次只要枚举所有的行,然后再暴力枚举第i~i+1个边即可(注意边界条件,因为是将值保存到右下角,所以边也要算右下角的)

#include
using namespace std;
const int N=405,M=2e6+5;
char s[M];
int mp[N][N];
bool vis[N*N];
vector<int>vec;
int a[N][N],top[N];
int main()
{
    int t;
    scanf("%d",&t);
    while(t--){
        int n,m,q;
        scanf("%d%d%d",&n,&m,&q);
        for(int i=1;i<=n;i++)
            for(int j=1;j<=m;j++)
                scanf("%d",&mp[i][j]);
        while(q--){
            int x,y;
            scanf("%d%d%s",&x,&y,s);
            for(int i=0;i<=n;i++)top[i]=0;
            vec.clear();
            int len=strlen(s);
            for(int i=0;i<len;i++){
                if(s[i]=='L')
                    x--,a[x+1][++top[x+1]]=y;
                else if(s[i]=='R')
                    x++,a[x][++top[x]]=y;
                else if(s[i]=='U')
                    y++;
                else
                    y--;
            }
            int ans=0;
            for(int i=1;i<=n;i++){
                sort(a[i]+1,a[i]+1+top[i]);
                for(int j=1;j<=top[i];j+=2)
                    for(int k=a[i][j]+1;k<=a[i][j+1];k++)
                        if(!vis[mp[i][k]])
                            ans++,vis[mp[i][k]]=1,vec.push_back(mp[i][k]);

            }
            printf("%d\n",ans);
            for(int i:vec)
                vis[i]=0;
        }
    }
    return 0;
}

你可能感兴趣的:(想法)