URAL 1260 Nudnik Photographer 簡單的遞推
阿新 • • 發佈:2019-01-30
給出N個數,分別是1,2,3 . . . . . .N,然後回答按照兩項規則排列這N個數的方案數。
1,兩個相鄰的數的差不能超過2。
2,1必須放在第一個位置。
思路:對於第 n 個數的放置方案其實只需考慮 (n-1) 和 (n-2) 的情況。
1,(n-1)和(n-2)相鄰且在最後,此時可細分出兩種情況,即(n-2)在後面(情況1)和(n-1)在後面(情況2)。
2,(n-1)和(n-2)相鄰且不在最後面(情況3)。
3,(n-1)和(n-2)不相鄰,此時只有一種情況,即(n-1)在最後(情況4)。
第一種情況會衍生出第三和第四種,第二種可以衍生出第一和第二種,第三種只會產生第三種,第四種只會產生第二種。
故狀態轉移方程為:
for(i = 3;i <= 55; ++i)
{
dp[1][i] = dp[2][i-1];
dp[2][i] = dp[2][i-1] + dp[4][i-1];
dp[3][i] = dp[1][i-1] + dp[3][i-1];
dp[4][i] = dp[1][i-1];
}
dp[i][j] 代表 j 個數時第i 種情況的方案數。
下面是AC程式碼。雖然這道題很簡單,但還是很慶幸思維方式的轉變。
#include <iostream> #include <algorithm> #include <cstdlib> #include <cstdio> #include <cstring> #include <queue> #include <cmath> #include <stack> #pragma comment(linker, "/STACK:1024000000"); #define LL long long int #define ULL unsigned long long int #define _LL __int64 using namespace std; _LL dp[5][60]; int main() { int i; dp[1][1] = 0; dp[2][1] = 1; dp[3][1] = 0; dp[4][1] = 0; dp[1][2] = 0; dp[2][2] = 1; dp[3][2] = 0; dp[4][2] = 0; for(i = 3;i <= 55; ++i) { dp[1][i] = dp[2][i-1]; dp[2][i] = dp[2][i-1] + dp[4][i-1]; dp[3][i] = dp[1][i-1] + dp[3][i-1]; dp[4][i] = dp[1][i-1]; } scanf("%d",&i); printf("%I64d\n",dp[1][i] + dp[2][i] + dp[3][i] + dp[4][i]); return 0; }