POJ 1416 Shredding Compan【題解報告|DFS-0MS】

在這裏插入圖片描述
題目鏈接

題目大意

公司現在要發明一種新的碎紙機,要求新的碎紙機能夠把紙條上的數字切成最接近而不超過target值。比如,target的值是50,而紙條上的數字是12346,應該把數字切成四部分,分別是1、2、34、6。因爲這樣所得到的和 43 (= 1 + 2 + 34 + 6) 是所有可能中最接近而不超過50的。(比如1, 23, 4, 和6 就不可以,因爲它們的和不如43接近50,而12, 34, 6也不可以,因爲它們的和超過50了。碎紙還有以下三個要求:

  • 如果target的值等於紙條上的值,則不能切。
  • 如果沒有辦法把紙條上的數字切成小於target,則輸出error。如target是1而紙條上的數字是123,則無論你如何切得到的和都比1大。
  • 如果有超過一種以上的切法得到最佳值,則輸出rejected。如target爲15,紙條上的數字是111,則有以下兩種切法11、1或者1、11.

你的任務是編寫程序對數字進行劃分以達到最佳值。

思路分析

設輸入的target和待切割的變量如下:

int a;
string b;
while (cin >> a >> b && a)

用DFS搜索所有可能的切割方式,函數如下:

//當前總和sum,前面積累了pre,到了第k個元素
void dfs(int k, int sum, int pre) 

用一個變量pre記錄前面累計的值,比如1234,pre=123時表示前三位累積了起來。當遍歷完所有位數時,我們對答案進行更新

	if (k == b.size() && sum + pre <= a) {
		t.push_back(pre);//t存儲一直以來切割的數字,res存儲答案
		if (sum + pre > mi)mi = pre + sum, res = t, sign = 1;//越接近a越好
		else if (sum + pre == mi) sign = 0;
		t.pop_back();
		return;
	}

可以進行一步剪枝,當前累計的值已經超過target就沒有繼續搜索的必要了

	if (pre + sum > a || k >= b.size())return;

否則,我們對b的第k位數有兩種操作方式

  • 將其作爲單獨的一個數,也就是說如果b=12345,pre=123,那麼我們將pre存下來,將4單獨作爲pre傳下去。
  • 將其和前面傳入的pre進行拼湊,即拼成1234傳下去。
	t.push_back(pre);
	dfs(k + 1, sum + pre, b[k] - '0');//單獨作爲一個元素
	t.pop_back();
	//作爲高位傳下去
	dfs(k + 1, sum, pre * 10 + b[k] - '0');//與前面結合成爲一個高位

完整代碼:

//208K	0MS
#define inf 0x3f3f3f3f
#define vec vector<int>
#define ll long long
#define P pair<int,int>
#define MAX 10005

int a, sign, mi;
vec res, t;
string b;

//當前總和sum,前面積累了pre,到了第k個元素
void dfs(int k, int sum, int pre) {
	if (k == b.size() && sum + pre <= a) {
		t.push_back(pre);
		if (sum + pre > mi)mi = pre + sum, res = t, sign = 1;//越接近a越好
		else if (sum + pre == mi) sign = 0;
		t.pop_back();
		return;
	}
	if (pre + sum > a || k >= b.size())return;

	t.push_back(pre);
	dfs(k + 1, sum + pre, b[k] - '0');//單獨作爲一個元素
	t.pop_back();
	//作爲高位傳下去
	dfs(k + 1, sum, pre * 10 + b[k] - '0');//與前面結合成爲一個高位
}

int main() {
	while (cin >> a >> b && a) {
		sign = 1; mi = 0; t.clear(); res.clear();
		dfs(1, 0, b[0] - '0');

		if (res.size() == 0)printf("error\n");
		else if (sign == 0)printf("rejected\n");
		else {
			printf("%d", mi);
			for (int i = 0; i < res.size(); i++)
				printf(" %d", res[i]);
			printf("\n");
		}
	}
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章