[Blue Bridge Cup] [Algorithm Training VIP] Swing Sequence (Deep Search + Backtracking || Dynamic Programming)

Topic description
If a sequence satisfies the following properties, we will call it a wobble sequence:

  1. All numbers in the sequence are positive integers not greater than k;
  2. There are at least two numbers in the sequence.
  3. The numbers in the sequence are not equal to each other;
  4. 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
Insert picture description here
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 ) / ~

Published 668 original articles · praised 118 · 50,000+ views

Guess you like

Origin blog.csdn.net/starlet_kiss/article/details/105575262