hdu 2362 square(附网上的数据)【深搜】

一、原文大致意思:

给一堆长短不一的棍子。让你求这些棍子能不能组成一个正方形。如果可以输出“yes”,否者输出“no”。

二、网上的一些测试数据

(源数据在这里:http://poj.org/showmessage?message_id=95450)

10
20 491 1050 1123 376 1045 1391 656 190 1305 537 20 533 1193 465 398 1258 756 
1005 949 63
20 1431 949 852 616 899 1257 413 335 528 107 1126 146 782 571 407 114 1393 
681 1229 1340
20 715 321 723 362 778 156 402 25 145 414 571 835 198 393 289 851 390 234 
1288 450
20 1450 1289 710 1209 287 202 1394 732 480 1121 1246 286 146 1333 1467 926 
471 453 921 889
20 407 1269 625 577 184 617 1357 994 107 250 783 117 1352 1355 820 16 336 
147 697 1134
20 679 1102 1502 1321 374 1472 288 428 1210 1497 1244 1412 573 1224 654 1465 
528 891 1417 311
20 1063 872 1391 987 513 566 1258 831 1295 604 1512 549 365 712 1146 1133 89 
561 1065 1476
20 1515 1473 1033 159 312 502 1342 1097 1231 476 1419 737 1200 174 1486 1311 
1261 416 1109 43
20 930 1165 584 56 1122 858 955 564 932 375 1267 580 1515 553 423 467 605 
722 1183 792
20 1035 1338 77 1253 243 715 177 951 852 1409 736 1170 694 945 555 289 1410 
539 869 1059
no
yes
yes
yes
yes
no
no
yes
no
yes

三、思路

深度优先搜索,设立a[21]数组存储木棍长度,le[4]输出存储搜索到的4根木棍长度,vis[21]数组存储是否访问过该木棍。

四、AC代码:

#include 
#include 
using namespace std;

int T;    //T表示测试量
int n, le[4], a[21], s1, sum;    //n:木棍数,le[4]存好的木棍累计和。(只算3根就ok),sum:木棍总和,s1木棍和除以4表示正方形边长。
bool ok, vis[21];    //vis标记木棍是否已经访问。

void dfs(int x, int y) {    //正在考虑第x个边长,从第y根木棍开始搜索,
	if (ok) {
		return;
	}
	if (x == 4) {    //如果开始搜索第4条边了,这说明已经ok了。因为sum%4==0,并且已经有3条木棍长s1的木棍了,剩下的1条必定也为s1.
		ok = true;
		return;
	}
	if (le[x] > s1) {    //如果正考虑的第x根木棍累和大于s1,return
		return;
	} else if (le[x] == s1) {    //如果等于s1,那么就考虑下一条正方形边长。记住下次从1开始访问剩下的木棍。(我写成了y错了一次)
		dfs(x + 1, 1);
		return;
	} else {    //如果当前边还可以加木棍,那就加一根。
		for (int i = y; i <= n; i++) {
			if (!vis[i]) {
				vis[i] = true;
				le[x] += a[i];
				dfs(x, i + 1);
				le[x] -= a[i];
				vis[i] = false;
			}
		}
	}
}

int main() {
	cin >> T;
	while (T--) {
		sum = 0;
		
		cin >> n;
		for (int i = 1; i <= n; i++) {    //由于我的DFS函数从1开始判断,为了方便这里从1开始输入。
			cin >> a[i];
			sum += a[i];
		}
		s1 = sum / 4;
		if (sum % 4 != 0) {    //首先他得要求sum不为0.
			cout << "no" << endl;
		} else {
			ok = false;
			memset(le, 0, sizeof(le));
			memset(vis, 0, sizeof(vis));
			dfs(1, 1);    //这里就是DFS啦。
			if (ok) {
				cout << "yes" << endl;
			} else {
				cout << "no" << endl;
			}
		}
		
	}
	return 0;
} 

五、优化:

看了网上大神的思路:可以这样优化一下,把木棍从大到小排序,这样,剪枝的时候会在开始阶段减掉大量的子树。你看下面的结果(第3行是上面的程序,第1行是优化后的程序

/* 优化部分的增量代码*/

//    1. 添加sort头文件。
#include 

//    2. 在主函数的dfs(1, 1)语句前面添加这句话即可 */
sort(a + 1, a + n + 1, greater());    /* greater()表示int值从大到小排序 */

):运行时间从579ms减到了282ms。

你可能感兴趣的:(刷题)