HDU2589 正方形划分【DFS】

题目链接:

?pid=2589

题目大意:

有一个边长为L的正方形有L*L个小正方形,将N个小石子放在N个小正方形中,给你N个小石子所放

位置,那么问题来了:能否将这个变成为L的正方形分割成N个正方形,使得每个正方形中都含有1个

小石子,并且这N个正方形正好构成整个正方形。

测试样例1说明:

边长为5的大正方形里有8个小石子,正好能将大正方形分解成8个小正方形,且每个正方形中有1个

小石子。

思路:

用DFS来做这道题。用Num[i][j]来表示从(1,1)到(i,j)的矩形中有多少个小石子(用来计算小正方形

中含有的小石子数),用vis[][]表示将包含1个小石子的正方形区域覆盖,用x,y来表示当前分解的正

方形的左上角坐标,k表示正方形的边长。每次找到没有覆盖的区域,记录坐标(x,y),开始遍历小

正方形的边长,直到找到刚好包含1个小石子的正方形区域,将其覆盖,然后接着深搜找到没有覆盖

的区域……如果没有找到刚好包含1个小石子的正方形区域,将其回溯到没有覆盖的状态继续深搜。

如果所有区域都能被覆盖,则说明满足条件,返回1。

注:设x1 = x + k,y1 = y + k。则计算从(x,y)到(x1,y1)的正方形中包含的小石子个数Count为:

Count = Num[x1][y1] – Num[x1][y-1] – Num[x-1][y1] + Num[x-1][y-1]。

AC代码:

#include<iostream>#include<algorithm>#include<cstdio>#include<cstring>using namespace std;int Map[22][22],Num[22][22],vis[22][22],L,N;int DFS(){int x,y,flag = 1;for(int i = 1; i <= L; ++i)//找到未分割正方形的位置坐标{if(!flag)break;for(int j = 1; j <= L; ++j){if(!vis[i][j]){x = i;y = j;flag = 0;break;}}}int k = 0;while(x+k <= L && y+k <= L){int x1 = x + k;int y1 = y + k;int Count = Num[x1][y1] – Num[x1][y-1] – Num[x-1][y1] + Num[x-1][y-1];//计算当前正方形内点的数目if(Count > 1) //大于1不符合break;else if(Count == 1) //当前正方形中正好有1个点{for(int i = x; i <= x1; ++i)//填充该正方形for(int j = y; j <= y1; ++j)vis[i][j] = 1;if(DFS())//继续填充,满足所求条件返回1.return 1;for(int i = x; i <= x1; ++i)//回溯到未填充该正方形的状态for(int j = y; j <= y1; ++j)vis[i][j] = 0;}k++;}for(int i = 1; i <= L; ++i)//判断是否满足所求条件for(int j = 1; j <= L; ++j)if(!vis[i][j])return 0;return 1;}int main(){int T;cin >> T;while(T–){cin >> L >> N;memset(Num,0,sizeof(Num));memset(vis,0,sizeof(vis));memset(Map,0,sizeof(Map));for(int i = 0; i < N; ++i){int x,y;cin >> x >> y;Map[x][y] = 1;}for(int i = 1; i <= L; ++i)for(int j = 1; j <= L; ++j)Num[i][j] = Num[i-1][j] + Num[i][j-1] – Num[i-1][j-1] + Map[i][j];if(DFS())cout << "YES" << endl;elsecout << "NO" << endl;}return 0;}

,赚钱之道很多,但是找不到赚钱的种子,便成不了事业家。

HDU2589 正方形划分【DFS】

相关文章:

你感兴趣的文章:

标签云: