先贴一个题目链接D-Contest Construction
这个题是与J题相似的一个DP题目
这道题就是要你用给出的n个数字来构成一个k长度的数列a,使得这个数列a是递增序的时候,对于任意的有
且
然后问你满足条件的方案有多少个.
为了解决这个问题,我们需要先把这n个数字进行排序,然后就顺序地往后面取数字,这样一来,就可以保证取到的数字只会越来越大,并且不会出现重复的方案.
因为要取第个数字必须要知道第和第个数字,所以状态量中必然会出现两个连续数位上的取到的数字.
因此得到如下dp方程
int dp[maxk][maxn][maxn]{};//dp[t][j][k] 第t个题目,选择题目为i,上一个是j的方案数量dp[t][i][j]=sum(dp[t-1][j][k]),k<j<i $且$ d[i]≤d[j]+d[k]
最终答案就是
当然了,要提前设定好的值,也就是说,只要,就设定为1.
以下为AC代码,时间复杂度
一开始WA了一发,发现是没有开long long.
#include <bits/stdc++.h>
using namespace std;
#define int long long
const int maxn=55;
const int maxk=25;
int d[maxn];
int dp[maxk][maxn][maxn]{};//[t][j][k] 第 t 个题目,选择题目为 i ,上一个是 j . 的方案数量
signed main()
{
int n,k;
cin >> n >> k;
for(int i=1;i<=n;i++)
cin >> d[i];
sort(d+1,d+n+1);
for(int i=1;i<=n;i++)
{
for(int j=1;j<i;j++)
{
dp[2][i][j]=1;
}
}
for(int t=3;t<=k;t++)
{
for(int i=1;i<=n;i++)
{
for(int j=1;j<i;j++)
{
int sum = 0;
for(int k=1;k<j;k++)
{
if(d[i]<=d[j]+d[k])
{
sum+=dp[t-1][j][k];
}
}
dp[t][i][j]=sum;
}
}
}
int asw = 0;
for(int i=1;i<=n;i++)
{
for(int j=1;j<i;j++)
{
asw+=dp[k][i][j];
}
}
cout << asw << endl;
return 0;
}