算法競賽進階指南--模擬機器實現,把組合型枚舉改爲非遞歸

vector<int> chosen;
int stack[100010], top = 0, address = 0;

void call(int x, int ret_addr) { // 模擬計算機彙編指令call
	int old_top = top;
	stack[++top] = x; // 參數x
	stack[++top] = ret_addr; // 返回地址標號
	stack[++top] = old_top; // 在棧頂記錄以前的top值
}

int ret() { // 模擬計算機彙編指令ret
	int ret_addr = stack[top - 1];
	top = stack[top]; // 恢復以前的top值
	return ret_addr;
}

int main() {
	int n, m;
	cin >> n >> m;
	call(1, 0); // calc(1)
	while (top) {
		int x = stack[top - 2]; // 獲取參數
		switch (address) {
		case 0:
			if (chosen.size() > m || chosen.size() + (n - x + 1) < m) {
				address = ret(); // return
				continue;
			}
			if (x == n + 1) {
				for (int i = 0; i < chosen.size(); i++)
					printf("%d ", chosen[i]);
				puts("");
				address = ret(); // return
				continue;
			}
			call(x + 1, 1); // 相當於calc(x + 1),返回後會從case 1繼續執行
			address = 0;
			continue; // 回到while循環開頭,相當於開始新的遞歸
		case 1:
			chosen.push_back(x);
			call(x + 1, 2); // 相當於calc(x + 1),返回後會從case 2繼續執行
			address = 0;
			continue; // 回到while循環開頭,相當於開始新的遞歸
		case 2:
			chosen.pop_back();
			address = ret(); // 相當於原calc函數結尾,執行return
		}
	}
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章