下面的函數生成段之間的空間排列,返回false時,它不能產生任何更多:
template <typename SpaceIter>
bool next(SpaceIter start, SpaceIter finish)
{
for (SpaceIter i = start; i != finish; ++i)
{
// Find the first non-minimised space.
if (*i)
{
SpaceIter j = i; ++j;
if (j == finish)
return false;
int s = *i; // Remember *i, in case i == start.
// Preserve the invariant: Σ(space[i])
// i != start i == start
// ---------- -----------
// Minimise current.
*i = 0; // Gain = -s overwritten
// Increment the next.
++*j; // Gain = 1 1
// Adjust the first.
*start = s - 1; // Gain = s - 1 -1
// -----------------------
// Nett = 0 0
return true;
}
}
return false;
}
注意,這個算法需要在包括兩端的空間和工作在過剩空間 - 也就是說,如果長度爲S的空間在任一端,則S表示爲S,但如果S - 1在中間的某處,則空間S表示爲S,因爲內部空間必須長度爲1或更大。清楚的是,在這種表示中,所有空格的最小值爲零。您通過將第一個空格設置爲N + 1來初始化spaces
- Σ i = 0..N(長度 i + 1)並且其餘N + 1個空格爲0,其中N是序列的數量。
要完成故事,您需要測試給定的輸入是否與給定的輸入兼容,是否有給定的空格排列組合長度數組。
一個簡單的方法是在開始時將輸入轉換爲位集。然後將每個空間排列與長度數組一起轉換爲一個bitset並從輸入bitset中減去。如果結果爲空,則輸入有效。
警告:我對上述算法進行了相當仔細的分析,但是我對代碼做了很少的測試。下面是我寫的一個相當難看的試車手,在情況下,它可以幫助你自己的測試:
template <typename T, int N>
bool next(T (&spaces)[N])
{
return next(spaces, spaces + N);
}
const char* x(int n) { return "XXXXXXXXXX" + 10 - n; }
const char* s(int n) { return "----------" + 10 - n; }
int main(int argc, const char* argv[])
{
int spaces[] = { 4, 0, 0, 0 };
do
{
// I reverse the spaces to make segments shuffle left-to-right.
// This is a purely aesthetic thing. The order of permutations
// doesn't matter.
std::cout << s(spaces[3]) << x(2)
<< s(spaces[2] + 1) << x(1)
<< s(spaces[1] + 1) << x(1)
<< s(spaces[0])
<< "\n";
}
while (next(spaces));
}
什麼你嘗試這麼遠嗎?您可以與我們分享的任何代碼? – Bart
你必須處理用戶輸入「有效」的所有可能組合,意味着什麼? – leo
@Bart我沒有任何代碼,我真的只是試圖從概念上思考這個問題,而且我很難找到任何真正開始的方法 – user1038665