题目在此:http://poj.org/problem?id=1014
要看清题意呢,题中要求输入的是价值分别为1,2,3,4,5,6的大理石的个数,而不是6块价值为输入数字的大理石!选这个题主要想练习一下深搜。在网上看到了一段代码,深搜时使用了贪心算法虽然可以AC但是有很大的漏洞:
如测试数据(0 0 3 0 3 1)便会出现错误:
搜索时候会选中:价值为6,5,3的各一个进而判断出不可以分割。但是正确的分割方式应该是6+3+3+3=15。
这个是网上有漏洞的代码:
1 #include<iostream> 2 using namespace std; 3 4 int amount[7] = {0}; 5 int half_value = 0; 6 int flag = 0; 7 8 void DFS(int value, int pre){ 9 10 if(value == half_value){ 11 flag = 1; 12 return; 13 } 14 15 if(flag == 1){ //这个可以去掉的啊! 16 return; 17 } 18 19 int i = 0; 20 for(i = pre; i > 0; i--){ 21 if(amount[i]){ 22 if(i + value <= half_value){ 23 amount[i]--; 24 DFS(i + value, i); 25 26 if(flag == 1){ //不可少的,感受其作用,让递归栈中所有DFS结束 27 return; 28 } 29 } 30 } 31 } 32 } 33 34 35 int main(){ 36 37 int testcase = 1; 38 while(true){ 39 flag = 0; 40 int totalvalue = 0; 41 int N = 6; 42 int i = 1; 43 while(i <= N){ 44 cin >> amount[i]; 45 totalvalue += amount[i] * i; 46 i++; 47 } 48 49 if(!amount[1] && !amount[2] && !amount[3] && !amount[4] && !amount[5] && !amount[6]){ 50 break; 51 } 52 53 printf("Collection #%d:\n", testcase++); 54 if(totalvalue % 2 != 0){ 55 cout << "Can‘t be divided." << endl << endl; 56 continue; 57 } 58 59 half_value = totalvalue / 2; 60 DFS(0, 6); 61 62 if(flag){ 63 cout << "Can be divided." << endl; 64 } else { 65 cout << "Can‘t be divided." << endl; 66 } 67 cout << endl; 68 } 69 return 0; 70 }
有漏洞的代码
为了解决这个问题,在判定不能分割之前又加入了一个循环,即从价值为5,4...1的大理石开始深搜,这样就避免了以上代码的漏洞。因为贪心算法基本解决了大部分的情况,故这个循环不会引起超时。以下是修改过的代码:
#include<iostream> #include <string.h> #include<stdio.h> using namespace std; int amount[7] = { 0 }; int temp_amount[7] = { 0 };//存下原始输入值 int half_value = 0; int flag = 0; void DFS(int value, int pre) { if (value == half_value) { flag = 1; return; } int i = 0; for (i = pre; i > 0; i--) { if (amount[i]) { if (i + value <= half_value) { amount[i]--; DFS(i + value, i); if (flag == 1) { return; } } } } } int main() { int testcase = 1; while (true) { flag = 0; int totalvalue = 0; int N = 6; int i = 1; while (i <= N) { cin >> temp_amount[i]; totalvalue += temp_amount[i] * i; i++; } if (!temp_amount[1] && !temp_amount[2] && !temp_amount[3] && !temp_amount[4] && !temp_amount[5] && !temp_amount[6]) { break; } printf("Collection #%d:\n", testcase++); if (totalvalue % 2 != 0) { cout << "Can‘t be divided." << endl << endl; continue; } half_value = totalvalue / 2; memcpy(amount, temp_amount, 7 * sizeof(int)); DFS(0, 6); if (flag) cout << "Can be divided." << endl; else { for (int m = 6; m >= 1; m--) { if (!flag) { memcpy(amount, temp_amount, 7 * sizeof(int));//因为amount数组已经被操作,故需要恢复 DFS(0, m); } } if (!flag) cout << "Can‘t be divided." << endl; else cout << "Can be divided." << endl; } cout << endl; } return 0; }
(以后再进行补充呃)
时间: 2024-10-11 00:07:03