1.本质上升序列
我想到的是用回溯去找子集一个一个判断,当然这样的话会来的很慢,然后就在网上找到了大佬的方法,这东西居然是用动态规划来的,说是最长递增子序列的类似问题 ,感觉我好像写过类似的,但是去找了找居然没有,类似的是最长回文串,但是那玩意儿确实很不好理解
1.21动态规划(中等)-CSDN博客
最长回文串(回顾一下)
a和aa一定是,这样的话是a[i]==a[j]%%i-j<=1的情况,还有的话就是相差一定距离了,比如abcba,如果1-5是回文串,那么2-3一定是,不然就不满足回文串,所以在这样的条件下就可以写动态规划了
下面就分析这个题的解法,在别人的帖子里学习的·(蓝桥杯第十一届决赛)试题D:本质上升序列(动态规划)_蓝桥杯本质上升序列答案-CSDN博客
最长子序列问题
还有就是最长子序列的问题,给一串数字找到最长子序列,数据结构与算法之最长递增子序列-CSDN博客
流程大概就是遍历,找到比目前的数来的小,但是他的最长子序列又比目前的最长子序列来的要大,我们就更新,更新到要看的数据的前一个(比自己来的小但是有最长子序列的),更新完本身后再比较看看这个是不是最长的,如果是的话要更新总体最长的
#include <bits/stdc++.h>
using namespace std;
main()
{
int a[9]={10,22,9,33,21,50,41,60,80};
int n,i,j,cur,maxl=1;
int* dp=(int*)calloc(n,sizeof(int));
dp[0]=1;
n=sizeof(a)/sizeof(a[0]);
for(i=1;i<n;i++)
{
cur=0;
for(j=0;j<i;j++)
{
if(a[i]>a[j])
{
if(dp[j]>cur)
{
cur=dp[j];
}
}
}
dp[i]=cur+1;
if(dp[i]>maxl) maxl=dp[i];
}
cout<<maxl;
}
本题解法
回到本题,其实就是来看每一个字母的递增序列有多少,也就是说我们想做的不是找到最长子序列是有多长,而是从过程中入手,计算有几个递增子序列
在这个代码里遇到了几个常见的错误,首先就是memset函数,它只能初始化成0和-1,最开始想设置成1结果搞错了,第二就是i和j的顺序,要注意一下,这个题的解法很巧妙的地方在于如果是重复出现的,要剪掉重复的,其实就是剪掉它之前的递增子序列数,也就是f(j)
#include <bits/stdc++.h>
using namespace std;
main()
{
string s;
cin>>s;
long long i,j,n,ans=0;
n=s.size();
cout<<n<<endl;
long long dp[n];
for(i=0;i<n;i++) dp[i]=1;
for(i=1;i<n;i++)
{
for(j=0;j<i;j++)
{
if(s[i]>s[j])
dp[i]+=dp[j];
else if(s[i]==s[j])
dp[i]-=dp[j];
}
}
for(i=0;i<n;i++)
{
cout<<dp[i]<<endl;
ans+=dp[i];
}
cout<<ans;
}
2.排列距离
看着感觉很难,去查了一下发现这东西居然叫康托展开,原理是如果n个数字或者字符全排列,每个元素只出现一次,从小到大按字典排列好,从0开始给他们编号,从字符串映射到编号就是康托展开。
第十三届蓝桥杯 C/C++ 大学 A 组 排列距离 康托和逆康托展开_蓝桥杯排列距离-CSDN博客
由列全排可得到其次序编号(康托展开),由次序编号可以得到对应的第几个全排列(逆康托展开)。
【数论系列】 康托展开-CSDN博客
对于选择题来说就是可以直接手算了,给字母按顺序编号序号,之后计算一下然后减下来,但是要写代码的话就有点难了,应该是要一个visit数组,然后按照这个编号的顺序去遍历,本来想自己写,发现别人思路和我差不多,但是代码要来的漂亮很多,思路也很清晰
好奇该,感觉我得代码没啥问题,但是一直跑出来的结果奇奇怪怪的,和别人的也对不上,不过我输出了一下他的代码发现有复数,但是我写的和他的又一样,奇奇怪怪的
#include <bits/stdc++.h>
using namespace std;
long long f[18];
void fl(int n)
{
f[0] = f[1] = 1; // 0的阶乘为1
for(int i = 2; i <= n; i++) f[i] = f[i - 1] * i;
}
long long kt(string s)
{
int i,j,tmp,n;
long long ans=1;
n=s.size();
for(i=0;i<n;i++)
{
tmp=0;
for(j=i+1;j<n;j++)
{
if(s[i]>s[j]) tmp++;
}
ans+=tmp*f[n-i-1];
}
return ans;
}
main()
{
fl(18);
string s1="aejcldbhpiogfqnkr",s2="ncfjboqiealhkrpgd";
long long sum1,sum2,sum3,sum4;
sum1=kt(s1);
sum2=kt(s2);
cout<<sum1<<" "<<sum2<<endl;
sum3=sum2-sum1;
sum4=f[17]-sum3;
cout<<min(sum3,sum4);
}