Topic description
If a sequence satisfies the following properties, we will call it a wobble sequence:
- All numbers in the sequence are positive integers not greater than k;
- There are at least two numbers in the sequence.
- The numbers in the sequence are not equal to each other;
- If the i-th number is larger than the i-th number, the i-th number is smaller than the i-th number; if the i-th number is smaller than the i-th number, the i-th number The number is larger than the i-th number.
For example, when k = 3, there are the following sequences:
1 2
1 3
2 1
2 1 3
2 3
2 3 1
3 1
3 2
There are 8 types. Given k, request the sequence that meets the above requirements The number.
Input The
input contains an integer k. (K <= 20)
Output
Output an integer, indicating the number of sequences that meet the requirements.
Sample input
3
Sample output
8
Ideas: At first I thought it was a memoized search, but I didn't figure out how to memorize it, so I violently dfs + backtracked and tried. Complexity is allowed (k <= 20).
code show as below:
#include<bits/stdc++.h>
#define ll long long
using namespace std;
const int maxx=2e1+1;
int a[maxx],vis[maxx];
int n;
inline void dfs(int num,int &ans)
{
if(num>n) return ;
if(num>=2)
{
ans++;
if(a[num]>a[num-1])
{
for(int i=a[num-1]-1;i>=1;i--)
{
if(vis[i]==0)
{
a[num+1]=i;
vis[i]=1;
dfs(num+1,ans);
vis[i]=0;
a[num+1]=i;
}
}
}
else
{
for(int i=a[num-1]+1;i<=n;i++)
{
if(vis[i]==0)
{
a[num+1]=i;
vis[i]=1;
dfs(num+1,ans);
vis[i]=0;
a[num+1]=0;
}
}
}
}
else
{
for(int i=a[num]-1;i>=1;i--)
{
if(vis[i]==0)
{
a[num+1]=i;
vis[i]=1;
dfs(num+1,ans);
vis[i]=0;
a[num+1]=0;
}
}
for(int i=a[num]+1;i<=n;i++)
{
if(vis[i]==0)
{
a[num+1]=i;
vis[i]=1;
dfs(num+1,ans);
vis[i]=0;
a[num+1]=0;
}
}
}
}
int main()
{
scanf("%d",&n);
int ans=0;
memset(vis,0,sizeof(vis));
for(int i=1;i<=n;i++)
{
a[1]=i;
vis[i]=1;
dfs(1,ans);
vis[i]=0;
}
cout<<ans<<endl;
return 0;
}
If k is larger, dfs is not so good, because backtracking is also time-consuming. Then we consider the way of dp. We can build a table based on the results of dfs and look for the rules in it. As shown in the following figure ( picture source ): the
ordinate represents the value of k, and the abscissa represents the number of the selected k numbers.
We can find that when the abscissa is 2, the answer is always (k-1) * k. When the abscissa is bigger, we can find the law.
State transfer equation: dp [i] [j] = dp [i-1] [j] + dp [i-1] [j-1]. The
code is as follows:
#include<bits/stdc++.h>
#define ll long long
using namespace std;
const int maxx=2e2+100;
int dp[maxx][maxx];
int n;
int main()
{
scanf("%d",&n);
for(int i=2;i<=n;i++) dp[i][2]=(i-1)*i;
for(int j=3;j<=n;j++)
{
for(int i=3;i<=n;i++) dp[i][j]=dp[i-1][j]+dp[i-1][j-1];
}
int ans=0;
for(int i=2;i<=n;i++) ans+=dp[n][i];
cout<<ans<<endl;
return 0;
}
The time complexity is only O (n ^ 2).
Come on a hard, ( o ) / ~