洛谷 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; }
细雨斜风作晓寒。淡烟疏柳媚晴滩。入淮清洛渐漫漫。
雪沫乳花浮午盏,蓼茸蒿笋试春盘。人间有味是清欢。