poj1020--DFS

来源:互联网 发布:服务器防火墙端口设置 编辑:程序博客网 时间:2024/05/22 20:55

一开始以为要用贪心,结果觉得处理起来很混乱

一开始用SideNum[]数组来存储各种尺寸的蛋糕的数目的思路是正确的,不应该存储输入的各块蛋糕的尺寸

思路和测试用例参考http://blog.csdn.net/lyy289065406/article/details/6683250


/*Problem: 1020   Memory: 148K  Time: 32MS Language: C++  Result: Accepted */#include<stdio.h>#include<string.h>int SideNum[11];//SideNum[0]存储蛋糕的块数,SideNum[i](1<=i<=10)表示边长为i的蛋糕的块数int col[41];//看做一个棋盘,从左到右,从上到下进行填充,(先选大块的蛋糕),该数组记录每一列已被填充的行数。   //因为最多有16块蛋糕,每块蛋糕最大边长为10,所有整个蛋糕的最大面积为16*10*10=1600=40*40,即整个蛋糕的最大边长为40,col[0]不用int s;//s为整个蛋糕的边长int area;int dfs(int count);//深搜,如果不浪费则返回1,否则返回0int main(){int t;//t为test case的数目int temp;int count;int sum;int i;scanf("%d", &t);while(t--){sum = 0;memset(SideNum, 0, sizeof(SideNum));//初始化SideNumscanf("%d %d", &s, &SideNum[0]);memset(col, 0, sizeof(col));//初始化col,将s列中每一列已填充的行数初始化为0count = 0;//记录边长大于s/2的蛋糕的块数,如果大于1,则无法满足area = 0;//累加已填充的面积for(i=1; i<=SideNum[0]; i++){scanf("%d", &temp);SideNum[temp]++;sum += temp*temp;//计算蛋糕总面积if(temp>s/2)count++;}if(count>1 || sum!=s*s){printf("HUTUTU!\n");continue;}if(dfs(0))printf("KHOOOOB!\n");elseprintf("HUTUTU!\n");}return 0;}int dfs(int count)//count为已经放入盒子的蛋糕数{int i, j;int min_col = 1;//保存当前可以放的位置的最小的列号,从1开始int min_row = 50;//保存当前可以放的最小列已经填充的行数int width;//寻找格子数被填充最少的列,靠左优先for(i=1; i<=s; i++){if(col[i] < min_row){min_col = i;min_row = col[i];}}for(j=10; j>=1; j--){if(SideNum[j] == 0)continue;//检查尺寸为size的蛋糕放入盒子时在纵向和横向是否越界if(min_col+j-1<=s && min_row+j<=s){width = 0;for (i = min_col; i<=min_col+j-1; i++){if(col[i]<=col[min_col]){width++;continue;}break;}if (width < j) continue;SideNum[j]--;for (i = min_col; i <= j+min_col-1; i++) {col[i] += j;}area += j*j;//累加总面积if(dfs(count + 1)){return 1;}for (i = min_col; i <= j+min_col-1; i++) //回溯{col[i] -= j;}SideNum[j]++;area -= j*j;}}if(area == s*s)return 1;elsereturn 0;}


原创粉丝点击