queue隊列練習:信息學奧賽:1361:產生數(Produce)

信息學奧賽:1361:產生數(Produce)

我參考了這篇文章

1361:產生數(Produce)

時間限制: 1000 ms 內存限制: 65536 KB
提交數: 3270 通過數: 1402
【題目描述】
給出一個整數n(n≤2000)和k個變換規則(k≤15)。規則:

① 1個數字可以變換成另1個數字;

② 規則中,右邊的數字不能爲零。

例如:n=234,k=2規則爲

2 → 5

3 → 6

上面的整數234經過變換後可能產生出的整數爲(包括原數)234,534,264,564共4種不同的產生數。

求經過任意次的變換(0次或多次),能產生出多少個不同的整數。僅要求輸出不同整數個數。

【輸入】
nkx1x2…xny1y2…yn
【輸出】
格式爲一個整數(滿足條件的整數個數)。

【輸入樣例】
234
2
2 5
3 6
【輸出樣例】
4

思路:
1.這題一開始我理解錯了,我以爲在原數的基礎上只執行一次變換規則,我說這題還不簡單嘛,結果我又想這和隊列有什麼聯繫。後來參考網上的答案才理解這道題說的什麼意思。
2.一個數num可以把某一位變成另一個數,整個數num就變成了另一個新數num1,在新數num1的基礎上又可以把某一位變成另一個數,新數num1又會變成另一個新數num2…這樣想很麻煩。
3.其實我們只用知道原數num的每一位數有多少種變換,然後每一位的可能的變換數相乘即可。
4.所以問題就拆分爲一個一位數在k個變換規則的約束下有多少種變換,題目示例2->4 ,3->5。也就是234這個數的第一位2可以變成4,這一位存在兩種可能結果,同理第二位3也存在兩種可能結果。所以結果就是4=2*2。
5.如果變換規則是這樣的呢?2->3,3->4,3->5這就要用到隊列了,加上bfs的思想。

#include<iostream>
#include<cstring>
#include<queue>
using namespace std;
const int maxn = 16;  // 題目種的變換規則<=15
char num[5];   // 題目種的數<2000最多也就4位數,
int k;
int from[maxn], to[maxn];  // 存放變換規則
bool vis[maxn];    // 用來當作標記,訪問過的數不能再訪問了
long long ans = 1;

long long bfs() {
	int len = strlen(num);
	queue<int>q;
	for (int i = 0; i < len; i++) {   // 對num的每一位進行bfs
		int now = num[i] - '0';
		q.push(now);
		memset(vis, true, sizeof(vis));
		int temp = 1;
		while (!q.empty()) {	
			int top = q.front();
			for (int j = 0; j < k; j++) {
				if (top == from[j] && vis[to[j]]) {
					temp++;
					q.push(to[j]);
					vis[from[j]] = false;  // 2->5  5->2
					vis[to[j]] = false;   // 2->5 3->5
				}
			}
			q.pop();	
		}
		ans *= temp;
	}
	return ans;
}

int main() {
	cin >> num;
	cin >> k;
	for (int i = 0; i < k; i++)
		cin >> from[i] >> to[i];

	cout << bfs();
	//getchar();
	//getchar();
	return 0;
}

// 看上面的那篇參考文章大佬隊列的實現方式可以借鑑借鑑,

int q[10001];
int head = 0, tail = 0;
q[tail++] = num; // 往隊列裏面壓一個數
num = q[head]; // 取一個數
head++; 		// 彈出一個數

基礎算法學習我一直認爲是見多識廣而不是獨立非把題做出來不可。因爲沒這麼多的時間。
看了別人的答案才知道隊列還有這樣的實現方式,bfs不單單是針對二維圖形的上下左右。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章