贪心思路:
先预处理出h[i][j]数组,表示(i,j)位置的点到最近的‘x’的距离
然后从上到下,从左到右遍历:
每一行取h[i][j]最小的点放置(对后面结果影响最小,同时vis[j]==0可放置),放置后vis[j]置1。
当遇到‘x'时,清零该位置vis[j]值,同时重新取之后的h[i][j]最小的点即可
#include<iostream> #include<fstream> #include<cstdlib> #include<iomanip> #include<string> #include<cstring> #include<cstdio> #include<algorithm> #include<cmath> #define REP(i,l,r) for(int i=(l);i<=(r);++i) #define REP2(i,l,r) for(int i=(l);i>=(r);--i) #define CLR(a,v) memset(a,v,sizeof(a)) #define sqr(x) ((x)*(x)) #define SCAN(n) scanf("%d",&n) #define SCAN2(n,m) scanf("%d %d",&n,&m) #define SCANS(s) scanf("%s",s); #define PRINT(n) printf("%d\n",n) using namespace std; typedef long long ll; const int INF=1e9; const int MOD=(int)1e9+7; const int N=100010; /*------------------------------------------------------------------------*/ int h[5][5]; int vis[5]; char s[10]; int main(){ int n; while(SCAN(n)!=EOF&&n){ CLR(h,0); REP(i,1,n){ SCANS(s+1); REP(j,1,n) if(s[j]=='.') h[i][j]=1; else h[i][j]=0; } REP2(i,n-1,1) REP(j,1,n){ if(h[i][j]) h[i][j]+=h[i+1][j]; } int ans=0; CLR(vis,0); REP(i,1,n){ int cnt=5,p=0; REP(j,1,n+1){ if(!vis[j]&&h[i][j]&&h[i][j]<cnt){ cnt=h[i][j]; p=j; } if(!h[i][j]){ if(cnt<5){ ++ans; vis[p]=1; cnt=5; } vis[j]=0; } } } PRINT(ans); } return 0; }