已知数列a={1,2,3,...,n},将k个小于符号('<')和n-k-1个大于符号('>')插入数列中可以使其构成一个合法的不等式(0<=k<=n-1)。例如a={1,2},可以为1<2或2>1;a={1,2,3},可以为1<2<3、1<3>2、2>1<3、2<3>1、3>1<2、3>2>1。输入n、k,输出合法的不等式的排列数。为了防止结果超过范围,将结果除以2020取模。
解答:用符号d[n][k]表示输入为n、k时,输出合法的不等式的排列数。
当k=0或k=n-1时,d[n][k]=1;
当0<k<=n/2时,d[n][k] = x * d[n - 1][k - 1] + y * d[n - 1][k],其中x = n - k, y = k + 1;(下详)
当k>n/2时,d[n][k]=d[n][n-k]。
static int[,] a = new int[1000, 500];
int DynamicProgramming(int n, int k)
{
if (k < 0 || k > n - 1) return -1;
if (k == 0 || k == n - 1) return 1;
if (k > n / 2) return DynamicProgramming(n, n - k);
if (a[n - 1, k - 1] == 0)
a[n - 1, k - 1] = DynamicProgramming(n - 1, k - 1);
if (a[n - 1, k] == 0)
a[n - 1, k] = DynamicProgramming(n - 1, k);
int result = (n - k) * a[n - 1, k - 1] + (k + 1) * a[n - 1, k];
return result % 2020;
}
d[n][k]等于以上四种情况之和:
d[n - 1][k] 将 n 加在开头并加入一个大于号,即要求 n -1 个数时已经有了 k 个小于号;
d[n - 1][k - 1] 将 n 加在末尾并加入一个小于号,即要求 n -1 个数时已经有了 k -1 个小于号;
d[n - 1][k] * k 将 n 加在任意一个小于号之间并加入了一个大于号,即要求 n -1 个数时已经有了 k 个小于号,每个小于号都可以进行这样的一次插入;
d[n - 1][k - 1] * (n - k - 1) 将 n 加载任意一个大于号之间并加入了一个小于号,即要求n -1 个数时有了 k -1 个小于号。