(ps.学习打卡记录)
1 . 树的遍历
题意:给定二叉树节点个数,然后给定后序遍历和中序遍历,输出层序遍历。
先找到根节点,记录根节点信息,然后递归处理左子树和右子树。
#include <iostream>
#include <vector>
using namespace std;
int tree[1500];
int last[1500], mid[1500], n;
int ser(int val)
{
for(int i=1;i<=n;++i)
{
if(mid[i]==val)
return i;
}
return 0;
}
int vis[35]={0};
void Merage_get(int val, int cnt) {
tree[cnt] = val;vis[val]=1;
int pos = ser(val);
for (int i = 1; i < n; ++i) {
int cur = last[i];
int k1 = ser(cur);
int k2 = ser(last[i+1]);
if (k1 < pos && k2 >= pos&&!vis[cur]) {
Merage_get(cur, 2 * cnt);
} else if (k1 > pos && k2 <= pos&&!vis[cur]) {
Merage_get(cur, 2 * cnt + 1);
}
}
}
int main() {
cin >> n;
for (int i = 1; i <= n; ++i) {
cin >> last[i];
}
for (int i = 1; i <= n; ++i) {
cin >> mid[i];
}
tree[1] = last[n];
Merage_get(last[n], 1);
vector<int> ans;
for (int i = 1; i <= 1400; ++i) {
if (tree[i])
ans.emplace_back(tree[i]);
}
for (int i = 0; i < ans.size(); ++i) {
cout << ans[i] << (i + 1 == ans.size() ? '\n' : ' ');
}
return 0;
}
2 . 摘花生
题意:从 ( 1 , 1 ) (1,1) (1,1) 出发,只能向下或者向右走,每走一步都可以摘取相应的花生数量,问最后到达 ( n , m ) (n,m) (n,m) 的时候最多能摘多少。
基本 d p dp dp 思路,每个点只能由上面或者左面到底,选择能取更多的一条线路。
(背包问题,组合模型;路线模型;最长上升子序列,线性模型)
#include<iostream>
#include<algorithm>
using namespace std;
int dp[102][200];
int main()
{
int q;cin>>q;
while(q--)
{
int n,m;cin>>n>>m;
int k[200][200];
for(int i=1;i<=n;++i)
{
for(int j=1;j<=m;++j)
{
cin>>k[i][j];
}
}
for(int i=1;i<=n;++i)
{
for(int j=1;j<=m;++j)
{
dp[i][j]=max(dp[i-1][j]+k[i][j],dp[i][j-1]+k[i][j]);
}
}
cout<<dp[n][m]<<endl;
}
}
3 . 最长上升子序列
题意:给定一个长度为 N N N 的数列,求数值严格单调递增的子序列的长度最长是多少。
经典 d p dp dp ,每一次添加一个数,使得得到的子序列严格递增,则答案 + 1 +1 +1 。
#include<iostream>
#include<algorithm>
using namespace std;
int main(){
int n;cin>>n;
int a[1001]={0};
int dp[1001]={0};
for(int i=1;i<=n;++i) cin>>a[i];
for(int i=1;i<=n;++i)
{
dp[i]=1;
for(int j=1;j<=i;++j)
{
if(a[j]<a[i])
dp[i]=max(dp[j]+1,dp[i]);
}
}
int ans=0;
for(int i=1;i<=n;++i) ans=max(ans,dp[i]);
cout<<ans<<endl;
return 0;
}
4 . 波动数列
题意:观察这个数列:1 3 0 2 -1 1 -2 …
这个数列中后一项总是比前一项增加2或者减少3,且每一项都为整数。
栋栋对这种数列很好奇,他想知道长度为 n n n 和为 s s s 而且后一项总是比前一项增加 a a a 或者减少 b b b 的整数数列可能有多少种呢?(方案数可能很大,对 100000007 100000007 100000007 取模)
本质上是个组合问题( d p dp dp),问的其实是选某些数使得等式成立的方案数。有时间了再贴分析过程,现在先直接上代码。(怕是没啥时间了,白天上课,晚上备赛写题,这时间哪里够用啊TvT
#include<iostream>
using namespace std;
const int MOD = 100000007;
int n,a,b,s;
int mode(int a,int b)
{
return (a%b+b)%b;
}
int main()
{
int dp[1002][1002];
dp[0][0]=1;
cin>>n>>s>>a>>b;
for(int i=1;i<n;++i)
{
for(int j=0;j<n;++j)
{
dp[i][j]=(dp[i-1][mode(j-i*a,n)]+dp[i-1][mode(j+i*b,n)])%MOD;
}
}
cout<<dp[n-1][(s%n+n)%n]<<endl;
}