洛谷 P1524 十字绣

题目背景

考古学家发现了一块布,布上做有针线活,叫做“十字绣”,即交替地在布的两面穿线。

题目描述

布是一个n*m的网格,线只能在网格的顶点处才能从布的一面穿到另一面。每一段线都覆盖一个单位网格的两条对角线之一,而在绣的过程中,一针中连续的两段线必须分处布的两面。给出布两面的图案(实线代表该处有线,虚线代表背面有线),问最少需要几针才能绣出来?一针是指针不离开布的一次绣花过程。

输入输出格式

输入格式:

 

第1行两个数N和M(1<=N,M<=200)。

接下来N行每行M个数描述正面。

再接下来N行每行M个数描述反面。

每个格子用.(表示空),/(表示从右上角连到左下角),\(表示从左上角连到右下角)和X(表示连两条对角线)表示

 

输出格式:

 

一个数,最少要用的针数。

 

输入输出样例

输入样例#1:
4 5
.....
.\...
..\..
.....
.....
....\ 
.\X..
.....
输出样例#1:
4
思路:然而我并不会(⊙o⊙)…可能是并查集吧!
#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
using namespace std;
int n,m,num,sum,ans;
int map[300][300];
char s[3][201][201];
int b[50000],c[50000];
int fa[50000],val[50000],vis[50000];
int find(int x){
    if(fa[x]==x)    return x;
    else return fa[x]=find(fa[x]);
}
int main(){
    scanf("%d%d",&n,&m);
    for(int i=1;i<=n;i++)
        scanf("%s",s[1][i]);
    for(int i=1;i<=n;i++)
        scanf("%s",s[2][i]);
    for(int k=1;k<=2;k++)
        for(int i=1;i<=n;i++)
            for(int j=0;j<m;j++){
                if(s[k][i][j]=='/'||s[k][i][j]=='X'){
                    if(map[j+2][i]==0){
                        num++;
                        fa[num]=num;
                        map[j+2][i]=num;
                    }
                    if(map[j+1][i+1]==0){
                        num++;
                        fa[num]=num;
                        map[j+1][i+1]=num;
                    }
                    val[map[j+2][i]]+=2*k-3;
                    val[map[j+1][i+1]]+=2*k-3;
                    int dx=find(map[j+2][i]);
                    int dy=find(map[j+1][i+1]);
                    if(dx!=dy)    fa[dy]=dx;
                }
                if(s[k][i][j]==92||s[k][i][j]=='X'){
                    if(map[j+1][i]==0){
                        num++;
                        fa[num]=num;
                        map[j+1][i]=num;
                    }
                    if(map[j+2][i+1]==0){
                        num++;
                        fa[num]=num;
                        map[j+2][i+1]=num;
                    }
                    val[map[j+1][i]]+=2*k-3;
                    val[map[j+2][i+1]]+=2*k-3;
                    int dx=find(map[j+1][i]);
                    int dy=find(map[j+2][i+1]);
                    if(dx!=dy)    fa[dy]=dx;
                }
            }
    for(int i=1;i<=num;i++){
        int dx=find(i);
        if(vis[dx]==0){
            sum++;
            c[sum]=dx;
            vis[dx]=1;
        }
        b[dx]=b[dx]+abs(val[i]);
    }
    for(int i=1;i<=sum;i++){
        if(b[c[i]]==0)    b[c[i]]=1;
        ans=ans+(b[c[i]]+1)/2;
    }
    cout<<ans;
}

 

 
posted @ 2017-09-23 21:05  一蓑烟雨任生平  阅读(323)  评论(0编辑  收藏  举报