# DFS# Backtracking# Combinatorics

d108 - NOIP 2008 2.火柴棍等式

🔗 前往 ZeroJudge 原題

題目描述

題目要求計算使用給定的火柴棍數量 n,可以組成多少個形如 "A + B = C" 的等式。其中 A、B、C 都是用火柴棍拼成的非負整數,且等式中的加號和等號各自需要兩根火柴棍。

解題思路

這道題可以使用深度優先搜尋 (DFS) 或回溯法來解決。基本思路是枚舉所有可能的 A、B、C 的組合,並檢查它們是否滿足以下條件:

  1. A、B、C 的火柴棍數量之和等於 n
  2. A + B = C。
  3. A、B、C 的最高位不能為 0 (除非它們是 0)。

程式碼中,m[i] 儲存了拼寫數字 i 所需的火柴棍數量。dfs 函數遞迴地構建 A、B、C,並檢查是否滿足條件。type 變數用於追蹤目前正在構建的數字是 A、B 還是 C。

複雜度分析

  • 時間複雜度: O(10^n)。由於火柴棍數量有限,且每個數字的火柴棍數量也是有限的,因此搜尋空間的大小是有限的。
  • 空間複雜度: O(n)。主要來自於遞迴調用的堆疊空間。

程式碼

#include <iostream>
using namespace std;
int m[10]={6,2,5,5,4,5,6,3,7,6},n,ans;
void dfs(int x1,int y1,int sum,int tmp,int type){
	if(tmp>n||sum>x1+y1)return;
	if(type==1){
		for(int i=0;i<10;++i){
			if(x1!=0)dfs(x1*10+i,y1,sum,tmp+m[i],1);
		}
		for(int i=0;i<10;++i){
			dfs(x1,i,sum,tmp+m[i],2);
		}
	}
	else if(type==2){
		for(int i=0;i<10;++i){
			if(y1!=0)dfs(x1,y1*10+i,sum,tmp+m[i],2);
		}
		for(int i=0;i<10;++i){
			dfs(x1,y1,i,tmp+m[i],3);
		}
	}
	else{
		if(tmp==n&&x1+y1==sum){
		//	cout << x1 << " " << y1 << " " << sum << "\n";
			++ans;
			return;
		}
		for(int i=0;i<10;++i){
			if(sum!=0)dfs(x1,y1,sum*10+i,tmp+m[i],3);
		}
	}
}
int main(){
	while(cin >> n){
		ans=0;
		n-=4;
		for(int i=0;i<10;++i){
			dfs(i,0,0,m[i],1);
		}
		cout << ans << "\n";
	}
}

Discussion