OJ-POJ1020-DFS

这篇博客介绍了如何使用深度优先搜索(DFS)解决一个编程竞赛题目——POJ1020。题目要求将一个给定边长的正方形蛋糕无损地分割成边长不超过10的小正方形蛋糕,且小蛋糕总数不超过16个。文章中提到了边界条件,并展示了如何用两个数组partMap和totalCou来存储小蛋糕的状态和位置信息,同时注意判断非法状态,如超出蛋糕范围和无法放下小蛋糕的情况。最后,博客给出了获得正确答案(AC)的代码。
摘要由CSDN通过智能技术生成

这题DFS通过不难,大意:

1,给一个正方形蛋糕,边长已知;
  2,无损分成正方形小蛋糕;

根据边界条件:

1,小蛋糕边长 <= 10

2,小蛋糕数目 <= 16

设定两个数组:

1,int partMap[]:存储小蛋糕状态,[下标]小蛋糕边长,[值]小蛋糕数量

2,int totalCou[]:存储未填状态,[下标]纵坐标,[值]最小横坐标

需要注意不符合条件的判断。

1,超界:加入之后超过蛋糕

2,放不下:加入的时候放不下

AC代码如下:

package poj10x;

/*
 * 	status : Accept
 * 	Memory	Time
 * 	3116K	860MS
 */

/*
 * 	text file encoding : utf8
 * 	大意:
 * 		1,给一个正方形蛋糕,边长已知;
 * 		2,无损分成正方形小蛋糕;
 * 	输入:
 * 		2(测试用例数)
 * 		4 8 1 1 1 1 1 3 1 1(边长,小蛋糕数,小蛋糕边长)
 * 		5 6 3 3 2 1 1 1
 * 	输出:
 * 		能,KHOOOOB!
 * 		否,HUTUTU!
 */

import java.util.Arrays;
import java.util.Scanner;

public class P1020 {
	static int partMap[] = new int[11];	//小蛋糕Map,[下标]边长,[值]个数
	static int totalCou[] = new int[41];	//未填,[下标]纵坐标,[值]最小横坐标
	static int totlLen, numOfPart, sumOfPartArea;
	static boolean isSolved;
	public static void main(String args[]) {
		int numOfTest, index, partLen, countOfMaxHalf;
		Scanner scanner = new Scanner(System.in);
		numOfTest = scanner.nextInt();
	    while (numOfTest -- > 0) {
	        Arrays.fill(partMap,0);
	        for(index = 1; index <= 40; index ++) {
	        	totalCou[index] = 1;
	        }
	    	totlLen = scanner.nextInt();
	    	numOfPart = scanner.nextInt();
	        sumOfPartArea = 0;
	        isSolved = false;
	        countOfMaxHalf = 0;
	        for(index = 1; index <= numOfPart; index ++) {
	        	partLen = scanner.nextInt();
	            partMap[partLen] ++;
	            sumOfPartArea += partLen*partLen;
	            if (partLen > totlLen/2) {
	            	countOfMaxHalf ++;
	            }
	        }	//end of for(index = 1; index <= numOfPart; index ++)
	        if(countOfMaxHalf > 1 || sumOfPartArea != totlLen*totlLen) {
	        	System.out.println("HUTUTU!");
	        	continue;
	        } else {	//else of if(countOfMaxHalf > 1 || sumOfPartArea != totlLen*totlLen)
	        	isSolved = false;   // 表明这是一个存在就行的。
	        						// 在今后的使用中,尽量使用全局boolean来标记是否完成。
	        						// 少用方法返回boolean,自己在这上犯的错太多了。
	        	dfs(0);
		        if (isSolved) {
		        	System.out.println("KHOOOOB!");
		        } else {
		    		System.out.println("HUTUTU!");
		        }
	        }	//end of if(countOfMaxHalf > 1 || sumOfPartArea != totlLen*totlLen)
	    }	//end of while (numOfTest -- > 0)
	    scanner.close();
	}	//end of public static void main
	public static void dfs(int depthOfDFS) {
		int saveOfX = Integer.MAX_VALUE, saveOfY = 0;
	    if(depthOfDFS == numOfPart) {	//如果对所有的n个小正方形搜索完毕。
			isSolved = true;
			return;
		}
		//遍历纵坐标,保存最小横坐标,保存对应纵坐标。
		for(int indexOfY = 1; indexOfY <= totlLen; indexOfY ++) {
			if(totalCou[indexOfY] < saveOfX) {
				saveOfX = totalCou[indexOfY];
				saveOfY = indexOfY;
			}
		}	//end of for(int indexOfY = 1; indexOfY <= totlLen; indexOfY ++)
		//小蛋糕,检索大的。
		for(int indexOfPartMap = 10; indexOfPartMap >= 1; indexOfPartMap --) {
			if (partMap[indexOfPartMap] <= 0 || saveOfX+indexOfPartMap-1 > totlLen || saveOfY+indexOfPartMap-1 > totlLen) {
				continue;
			}
		    boolean isPlacedInFor = true;
			for(int indexOfSelectPart = saveOfY; indexOfSelectPart <= saveOfY+indexOfPartMap-1; indexOfSelectPart ++) {
				if(totalCou[indexOfSelectPart] > saveOfX) {
					isPlacedInFor = false;
					break;
				}
			}	//end of for(int indexOfSelectPart = saveOfY; indexOfSelectPart <= saveOfY+indexOfMap-1; indexOfSelectPart ++)
			if(! isPlacedInFor) {
				continue;
			}
			//开始填充
			for(int indexOfSelectPart = saveOfY;indexOfSelectPart <= saveOfY+indexOfPartMap-1; indexOfSelectPart ++) {
				totalCou[indexOfSelectPart] += indexOfPartMap;
			}
			partMap[indexOfPartMap] --;
			dfs(depthOfDFS + 1);
			partMap[indexOfPartMap] ++;
            for(int indexOfSelectPart = saveOfY;indexOfSelectPart <= saveOfY+indexOfPartMap-1; indexOfSelectPart ++) {
            	totalCou[indexOfSelectPart] -= indexOfPartMap;
            }
            //回溯结束
		}	//end of for(int indexOfMap = 10; indexOfMap >= 1; indexOfMap --)
	}	// end of public static void dfs(int depthOfDFS)
}


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值