洛谷 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;
}

 

 

转载于:https://www.cnblogs.com/cangT-Tlan/p/7582548.html

  • 0
    点赞
  • 0
    收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
©️2022 CSDN 皮肤主题:编程工作室 设计师:CSDN官方博客 返回首页
评论
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值