POJ 2718——Smallest Difference

問題描述

給定許多不同的十進制數字,您可以通過選擇這些數字的非空子集並按一定順序寫入來形成一個整數。其餘數字可以按某種順序寫下來以形成第二個整數。除非結果整數爲0,否則整數不能以數字0開頭
例如,如果給定數字0、1、2、4、6和7,則可以寫成整數對10和2467。當然,有很多方法可以形成這樣的整數對:210和764、204和176等。最後一對整數之間的差值的絕對值爲28,事實證明,由整數組成的其他整數對都沒有。上述規則可以取得較小的差異。

樣例輸入:
6(字串長度)
012467(字串內容)

樣例輸出:
28(204 - 176)

問題分析

這題借用了c++標準庫的一種函數 next_permutation(a, a+n);這函數的作用是對數組進行排列,可以求出數組的全排列。(這很關鍵)
題目信息點:給定數字,形成兩個不同的整數(不能以0開頭並且長度是一半一半(偶數情況)或者長度相差爲1(奇數情況)),求這兩個整數的最小差異(相減最小值)。

解題思想:就是把給定的整數拆成兩個長度相同數值不同整數,然後對兩個整數進行全排列。根據每次全排列的結果,然後選定差值最小的答案。

#include<iostream>
#include<algorithm>
using namespace std;

char s[10];
int a[15];
int x, y, n;
int res = INT_MAX;
 
//************************************
// Method:    暴力
// FullName:  窮竭搜索
// Access:    public 
// Returns:   void
// Idea: 全排列求差值
//************************************
int num(int i, int j)
{
	int x = 0;
	for (int k = i; k < j; k++)
	{
		x = x * 10 + a[k];
	}
	return x;
}
void solve()
{
	if (n == 0)
	{
		cout << n << endl;
		return;
	}
	int k = n / 2;
	do
	{
		//第一個是0則繼續下一個排列
		if (a[0] == 0 || a[k] == 0)	continue;
		
		//左開右臂
		int x = num(0, k);
		int y = num(k, n);
		res = min(res, abs(x - y));
	} while (next_permutation(a, a + n));

	cout << res << endl;
}
/////////////////////////SubMain/////////////////////////
int main()
{
	cin >> n;
	for (int i = 0; i < n; i++)
	{
		cin >> s[i];
		a[i] = s[i] - '0';
	}
	solve();
	return 0;
}
////////////////////////SubEnd////////////////////////////

注意:next_permutation這個函數一定得遵循do…while()結構,具體原因感興趣可以瞭解一下。
還有就是,next_permutation()函數是一種原址排列方式(就是在原來的數組上排列,結果也存在原來的數組,一旦使用後,數組也不再是原來的樣子)(原址排序也是一樣道理)

另外,還有一種更直接的暴力解法。
就是從頭遍歷,每2個數形成一個“方塊”,然後用數組記錄又多少個方塊,然後進行遍歷,每個方塊都有2選1的機會,也就是排列,當然方塊的順序也是可以改變的。

感興趣可以試一試,我試了一下,因爲過於複雜,就直接只用排列函數了(這函數具體使用請查看c++標準庫的函數)。

發佈了17 篇原創文章 · 獲贊 20 · 訪問量 5403
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章