动态规划P1

news2024/11/17 8:21:12

动态规划P1

请添加图片描述

1.数字三角形模型

1.1只取一条最大路或最小路

  • 1015. 摘花生

  • 只能向下或向右走,求最大能取多少花生

  • 记录每个点最大能取到多少花生,从左上一直推到右下角

  • d p [ i ] [ j ] = m a x ( d p [ i − 1 ] [ j ] , d p [ i ] [ j − 1 ] ) + a [ i ] [ j ] dp[i][j]=max(dp[i-1][j],dp[i][j-1])+a[i][j] dp[i][j]=max(dp[i1][j],dp[i][j1])+a[i][j]

  • 复杂度: O ( t n 2 ) O(tn^2) O(tn2)

    #include<bits/stdc++.h>
    using namespace std;
    const int MAXN = 101;
    int dp[MAXN][MAXN];
    int a[MAXN][MAXN];
    int main()
    {
    	int t;cin >> t;
    	while(t--)
    	{
    		memset(dp,0,sizeof(dp));
    		int r,c;cin >> r >> c;
    		for(int i = 1;i <= r;i++)
    		for(int j = 1;j <= c;j++)
    			cin >> a[i][j];
    		dp[1][1] = a[1][1];
    		for(int i = 3;i <= r + c;i++)//从小到大枚举步数
    		{
    			for(int _i = 1;_i <= r;_i++)
    			{
    				int _j = i - _i;
    				if(_j <= 0 || _j > c)
    					continue;
    				else
    				{
    					if(_i != 1)
    						dp[_i][_j] = dp[_i - 1][_j];
    					if(_j != 1)
    						dp[_i][_j] = max(dp[_i][_j],dp[_i][_j - 1]);
    					dp[_i][_j] += a[_i][_j];
    				}
    			}
    		}
    		cout << dp[r][c] << endl;
    	}
    }
    
  • 1018. 最低通行费

  • 同上,只是取最小值

  • d p [ i ] [ j ] = m i n ( d p [ i − 1 ] [ j ] , d p [ i ] [ j − 1 ] ) + a [ i ] [ j ] dp[i][j]=min(dp[i-1][j],dp[i][j-1])+a[i][j] dp[i][j]=min(dp[i1][j],dp[i][j1])+a[i][j]

#include<bits/stdc++.h>
using namespace std;
const int MAXN = 1e2 + 10;
int dp[MAXN][MAXN];
int main()
{
	int n;cin >> n;
	for(int i = 1;i <= n;i++)
	for(int j = 1;j <= n;j++)
	cin >> dp[i][j];
	for(int i = 3;i <= n*2;i++)
	{
		for(int _i = 1;_i <= n;_i++)
		{
			int _j = i - _i;
			if(_j <= 0 || _j > n)
				continue;
			int mi = 1e9 + 10;
			if(_j - 1 > 0)
				mi = min(mi,dp[_i][_j - 1]);
			if(_i - 1 > 0)
				mi = min(mi,dp[_i - 1][_j]);
			dp[_i][_j] += mi;
		}
	}
	cout << dp[n][n];
}

1.2取两条路,可重叠

  • 1027.方格取数
  • 取两条路得到最大值,我们就让两条路同时走,如果走到同一个格子就加一次
  • 复杂度: O ( n 3 ) O(n^3) O(n3)
#include<bits/stdc++.h>
using namespace std;
int dp[11][11][22];
int a[11][11];
int main()
{
	int n;cin >> n;
	int i,j,v;cin >> i >> j >> v;
	while(i != 0)
	{
		a[i][j] = v;
		cin >> i >> j >> v;
	}
	dp[1][1][2] = a[1][1];
	for(int i = 3;i <= n*2;i++)//枚举两条路的步数
	{
		for(int i1 = 1;i1 <= n;i1++)//枚举第一条路线的i
		{
			int j1 = i - i1;
			if(j1 <= 0 || j1 > n)
				continue;
			for(int i2 = 1;i2 <= n;i2++)//枚举第二条
			{
				int j2 = i - i2;
				if(j2 <= 0 || j2 > n)
					continue;
				int w = a[i1][j1] + a[i2][j2];
				if(i1 == i2)//走到同一个格子
					w -= a[i1][j1];
				int ma = 0;
				if(i1 - 1 > 0 && i2 - 1 > 0)
					ma = dp[i1 - 1][i2 - 1][i - 1];
				if(i1 - 1 > 0 && j2 - 1 > 0)
					ma = max(ma,dp[i1 - 1][i2][i - 1]);
				if(j1 - 1 > 0 && i2 - 1 > 0)
					ma = max(ma,dp[i1][i2 - 1][i - 1]);
				if(j1 - 1 > 0 && j2 - 1 > 0)
					ma = max(ma,dp[i1][i2][i - 1]);
				dp[i1][i2][i] = ma + w;
			}
		}
	}
	cout << dp[n][n][n*2];
}

1.3取两条路,不可重叠

  • 275. 传纸条
  • 那就默认让一条路的 i 1 i1 i1大于 i 2 i2 i2即可,这样两条路就没有相交点
  • 复杂度: O ( n 3 ) O(n^3) O(n3)
#include<bits/stdc++.h>
using namespace std;//假设第一条路径就是高于第二条路径
int a[51][51];
int dp[51][51][102];
int main()
{
	int m,n;cin >> m >> n;
	for(int i = 1;i <= m;i++)
	for(int j = 1;j <= n;j++)
		cin >> a[i][j];
	for(int i = 1;i <= m + n;i++)//枚举步数
	{
		for(int i1 = 1;i1 <= m;i1++)
		{
			int j1 = i - i1;
			if(j1 <= 0 || j1 > n)
				continue;
			for(int i2 = 1;i2 < i1;i2++)
			{
				int j2 = i - i2;
				if(j2 <= 0 || j2 > n)
					continue;
				int ma = 0;
				if(i1 - 1 > 0 && i2 - 1 > 0)
					ma = dp[i1 - 1][i2 - 1][i - 1];
				if(i1 - 1 > 0 && j2 - 1 > 0)
					ma = max(ma,dp[i1 - 1][i2][i - 1]);
				if(j1 - 1 > 0 && i2 - 1 > 0)
					ma = max(ma,dp[i1][i2 - 1][i - 1]);
				if(j1 - 1 > 0 && j2 - 1 > 0)
					ma = max(ma,dp[i1][i2][i - 1]);
				dp[i1][i2][i] = ma + a[i1][j1] + a[i2][j2];
			}
		}
	}
	cout << dp[m][m - 1][n + m - 1];
}

2.最长上升子序列模型

2.1求最长长度

  • 1017. 怪盗基德的滑翔翼

  • 1.贪心法:如果大于最后一个数,就直接加入,否则找第一个大于它的数替换,这样就实现了让后面有潜力的子序列能替换掉最大串

  • 复杂度: O ( n l o g 2 n ) O(nlog_2n) O(nlog2n)

#include<bits/stdc++.h>
using namespace std;
int a[101],b[101],c[101];
int main()
{
	int k;cin >> k;
	while(k--)
	{
		int n;cin >> n;
		int ptop = 1;
		cin >> a[1];
		c[1] = a[1];
		for(int i = 2;i <= n;i++)
		{
			int x;cin >> c[i];
			x = c[i];
			if(a[ptop] < x)
				a[++ptop] = x;
			else
				a[lower_bound(a + 1,a + 1 + ptop,x) - a] = x;
		}
		int pptop = 1;
		b[1] = c[n];
		for(int i = n - 1;i >= 1;i--)
		{
			int x = c[i];
			if(b[pptop] < x)
				b[++pptop] = x;
			else
				b[lower_bound(b + 1,b + 1 + pptop,x) - b] = x;
		}
		cout << max(ptop,pptop) << endl;
	}
}
  • 2.动态规划:存这个位置最长的串,从前往后枚举,每次都向前找最长的能插上的位置然后加1
  • 复杂度: O ( n 2 ) O(n^2) O(n2)
#include<bits/stdc++.h>
using namespace std;
const int MAXN = 101;
int a[MAXN],dp[MAXN];
int main()
{
	int k;cin >> k;
	while(k--)
	{
		int n;cin >> n;
		memset(dp,0,sizeof(dp));
		int ma = 0;
		a[0] = 10001;
		for(int i = 1;i <= n;i++)
			cin >> a[i];
		for(int i = 1;i <= n;i++)
		for(int j = 0;j < i;j++)
		if(a[j] > a[i])
		{
			dp[i] = max(dp[j] + 1,dp[i]);
			ma = max(dp[i],ma);
		}
		memset(dp,0,sizeof(dp));
		a[n + 1] = 10001;
		for(int i = n;i >= 1;i--)
		for(int j = i + 1;j <= n + 1;j++)
		if(a[j] > a[i])
		{
			dp[i] = max(dp[j] + 1,dp[i]);
			ma = max(dp[i],ma);
		}
		cout << ma << endl;
	}
}

2.2求最长山形

  • 1014. 登山

  • 482. 合唱队形

  • 从前往后和从后往前都求一遍,求最大和

  • 贪心法:复杂度 O ( n l o g 2 n ) O(nlog_{2}n) O(nlog2n)

#include<bits/stdc++.h>
using namespace std;
const int MAXN = 1e3 + 10;
int a[MAXN];
int b[MAXN],ans[MAXN];
int main()
{
	int n;cin >> n;
	int ptop = 1;
	cin >> a[1];
	b[1] = a[1];
	ans[1] = 1;
	for(int i = 2;i <= n;i++)
	{
		cin >> a[i];
		int x = a[i];
		if(x > b[ptop])
			b[++ptop] = x;
		else
			b[lower_bound(b + 1,b + 1 + ptop,x) - b] = x;
		ans[i] = ptop;
	}
	ptop = 1;
	b[1] = a[n];
	int ma = ans[n];
	for(int i = n - 1;i >= 1;i--)
	{
		int x = a[i];
		if(x > b[ptop])
			b[++ptop] = x;
		else
			b[lower_bound(b + 1,b + 1 + ptop,x) - b] = x;
		ma = max(ptop + ans[i] - 1,ma);
	}
	cout << ma;
}

2.3引索型最长子序列

  • 1012. 友好城市

  • a i a_i ai b i b_i bi都要递增

  • a i a_i ai排序,对排序后的 b i b_i bi做最长子序列

  • 复杂度: O ( n l o g 2 n ) O(nlog_2n) O(nlog2n)

#include<bits/stdc++.h>
using namespace std;
const int MAXN = 5e3 + 10;
pair<int,int> pa[MAXN];
int b[MAXN];
int main()
{
	int n;cin >> n;
	for(int i = 1;i <= n;i++)
		cin >> pa[i].first >> pa[i].second;
	sort(pa + 1,pa + 1 + n);
	b[1] = pa[1].second;
	int ptop = 1;
	for(int i = 2;i <= n;i++)
		if(pa[i].second > b[ptop])
			b[++ptop] = pa[i].second;
		else
			b[lower_bound(b + 1,b + 1 + ptop,pa[i].second) - b] = pa[i].second;
	cout << ptop;
}

2.4最少递增序列

  • 1010. 拦截导弹

  • 给一个序列,将其分成多个单调递增序列,求最少数量

  • 记录每个序列的最大值,枚举放下,如果放不下就增加一个序列来放

  • 复杂度: O ( n l o g 2 n ) O(nlog_2n) O(nlog2n)

#include<bits/stdc++.h>
using namespace std;
const int MAXN = 1e3 + 10;
int a[MAXN],b[MAXN],c[MAXN];
int main()
{
	int ptop = 0;
	int x,ma = 0;
	while(scanf("%d",&x) != EOF)
	{
		a[++ptop] = x;
	}
	int pptop = 1;c[1] = b[1] = a[ptop];
	int ans = 1;
	for(int i = ptop - 1;i >= 1;i--)
	{
		int x = a[i];
		int aim = lower_bound(c + 1,c + 1 + ans,x,[&](int a,int b){
			return a > b;
		}) - c;
		if(aim == ans + 1)
			c[++ans] = x;
		else
			c[aim] = x;
		if(b[pptop] <= x)
		{
			b[++pptop] = x;
		}
		else
		{
			b[upper_bound(b + 1,b + 1 + pptop,x) - b] = x;
		}
	}
	cout << pptop << endl << ans << endl;
}

2.5求最大的上升子序列

  • 1016. 最大上升子序列和
  • 动态规划暴力,找前面最大的可以放在后面的,就是把记录的长度换成总和,没有贪心做法
  • 复杂度: O ( n 2 ) O(n^2) O(n2)
#include<bits/stdc++.h>
using namespace std;
const int MAXN = 1e3 + 10,MAX = 1e4 + 10;
int a[MAXN];
int dp[MAX];
int main()
{
	int n;cin >> n;
	for(int i = 1;i <= n;i++)
	{
		int x;cin >> x;
		int ma = 0;
		for(int i = 1;i < x;i++)
		{
			ma = max(ma,dp[i]);
		}
		dp[x] = ma + x;
	}
	int ma = 0;
	for(int i = 1;i <= MAX - 1;i++)
		ma = max(ma,dp[i]);
	cout << ma << endl;
}

2.6最少分割单调子序列

  • 187. 导弹防御系统

  • 爆搜

  • 枚举每个位置是加入递增还是递减,然后深度优先搜索,得出一个答案,回溯然后用这个答案剪枝

  • 复杂度: O ( n 2 n ) O(n2^n) O(n2n)

#include<bits/stdc++.h>
using namespace std;
int a[51];
int ans = 999;
int ma[52];
int mi[52];
int n;
void dfs(int i,int ptop1,int ptop2){
	if(ptop1 + ptop2 >= ans) return;
	if(i == n + 1) ans = ptop1 + ptop2;
	else{
		int j;
		for(j = 1;j <= ptop1;j++)
			if(a[i] > ma[j])
				break;
		int pre = ma[j];
		ma[j] = a[i];
		if(j == ptop1 + 1)
			dfs(i + 1,ptop1 + 1,ptop2);
		else
			dfs(i + 1,ptop1,ptop2);
		ma[j] = pre;
		for(j = 1;j <= ptop2;j++)
			if(a[i] < mi[j])
				break;
		pre = mi[j];
		mi[j] = a[i];
		if(j == ptop2 + 1)
			dfs(i + 1,ptop1,ptop2 + 1);
		else
			dfs(i + 1,ptop1,ptop2);
		mi[j] = pre;
	}
}
int main()
{
	cin >> n;
	while(n != 0){
		ans = 999;
		for(int i = 1;i <= n;i++)
			cin >> a[i];
		dfs(1,0,0);
		cout << ans << endl;
		cin >> n;
	}
}

2.7最长公共上升子序列

  • 如果 a [ i ] = b [ j ] a[i]=b[j] a[i]=b[j],那么如果要接上这个,就要找前面最长的还小于它们的公共上升子序列,用 f [ i ] [ j ] f[i][j] f[i][j]来表示以 b [ j ] b[j] b[j]结尾的最长公共上升子序列,要找的就是 f m a x [ i ′ ] [ j ′ ] ( b [ j ′ ] < a [ j ] & & j ′ < j ) f_{max}[i'][j'](b[j']<a[j]\&\&j'<j) fmax[i][j](b[j]<a[j]&&j<j)
for(int i = 1;i <= n;i++)
for(int j = 1;j <= n;j++)
{
    if(a[i] == b[j]){
        int ma = 1;
        for(int k = 1;k < j;k++)
            if(a[i] > b[j])
            	ma = max(dp[i][k] + 1,ma);
        dp[i][j] = ma;
    }
}
  • 三重循环会爆时间,因此要简化,我们可以看到 j j j是递增的,而 k k k循环是找 j j j之前的东西,所以我们只要在 j j j循环内找即可,推一个 j j j找一次
for(int i = 1;i <= n;i++)
{
    int ma = 1;
    for(int j = 1;j <= n;j++)
    {
        if(a[i] == b[j]) dp[i][j] = ma;
        else if(a[i] > b[j]) ma = max(dp[i][j] + 1,ma);
    }
}
  • 综上所述
  • 复杂度: O ( n 2 ) O(n^2) O(n2)
#include<bits/stdc++.h>
using namespace std;
int dp[3001][3001];
int a[3001],b[3001];
int main()
{
	int n;cin >> n;
	for(int i = 1;i <= n;i++)
		cin >> a[i];
	for(int i = 1;i <= n;i++)
		cin >> b[i];
	for(int i = 1;i <= n;i++)
	{
		int ma = 1;
		for(int j = 1;j <= n;j++)//从前往后,尝试加入a[i]
		{
			dp[i][j] = dp[i - 1][j];
			if(a[i] == b[j])//尝试加入
			dp[i][j] = max(dp[i][j],ma);
			else if(a[i] > b[j])
			ma = max(dp[i][j] + 1,ma);
		}
	}
	int ma = 0;
	for(int i = 1;i <= n;i++)
		ma = max(dp[n][i],ma);
	cout << ma << endl;
}

addtion 2.8最长下降子序列及计不同序列数量

  • G - 低价购买

  • 用dp来做最长下降子序列,每次得到一个数就向前找比它大的然后尝试接上

  • 计数时有可能重复计数,那么我们取一个数是如果前面有相同的数,那么就把那个数抛弃掉,因为对后面的数来说接前面的数还是这个数都一样并且接后面的那个相同的数更有可能更长

#include<bits/stdc++.h>
using namespace std;
const int N = 5e3 + 10;

pair<int,int> dp[N];
int a[N];

int main()
{
	int n;cin >> n;
	for(int i = 1;i <= n;i++)
		cin >> a[i];
	int ma = 0;
	for(int i = 1;i <= n;i++){
		dp[i] = {1,1};
		for(int j = i - 1;j >= 1;j--){
			if(a[i] < a[j]){
				if(dp[j].first + 1 > dp[i].first){
					dp[i].first = dp[j].first + 1;
					dp[i].second = dp[j].second;
				}else if(dp[j].first + 1 == dp[i].first)
					dp[i].second += dp[j].second;
			}else if(a[i] == a[j])
				dp[j] = {0,0};
		}
		ma = max(ma,dp[i].first);
	}
	int cnt = 0;
	for(int i = 1;i <= n;i++)
		if(ma == dp[i].first)
			cnt += dp[i].second;
	cout << ma << ' ' << cnt << endl;
}

3.背包模型

3.1 01背包问题

  • 423. 采药

  • 枚举物品,每次尝试放入物品,如果放入后状态更好就替换,否则不换 d p [ i ] [ j ] = m a x ( d p [ i − 1 ] [ j − t ] + v , d p [ i − 1 ] [ j ] ) dp[i][j]=max(dp[i-1][j - t]+v,dp[i-1][j]) dp[i][j]=max(dp[i1][jt]+v,dp[i1][j])

  • 如果从后往前更新,就不会产生一个物品取两次的情况了,所以有 d p [ j ] = m a x ( d p [ j − t ] + v , d p [ j ] ) dp[j]=max(dp[j-t]+v,dp[j]) dp[j]=max(dp[jt]+v,dp[j])

  • 时间复杂度: O ( t m ) O(tm) O(tm)

  • d p [ ] [ ] dp[][] dp[][]

#include<bits/stdc++.h>
using namespace std;
int dp[101][1001];
int main()
{
	int t,m;cin >> t >> m;
	for(int i = 1;i <= m;i++){
		
		int tt,v;cin >> tt >> v;
		for(int j = 1;j <= t;j++)
			if(j - tt >= 0)
				dp[i][j] = max(dp[i - 1][j - tt] + v,dp[i - 1][j]);
			else
				dp[i][j] = dp[i - 1][j];
	}
	cout << dp[m][t];
}
  • d p [ ] dp[] dp[]
#include<bits/stdc++.h>
using namespace std;
int dp[1001];
int main()
{
		int t,m;cin >> t >> m;
		for(int i = 1;i <= m;i++){
			int tt,v;cin >> tt >> v;
			for(int j = t;j >= tt;j--)
				dp[j] = max(dp[j - tt] + v,dp[j]);
		}
		cout << dp[t] << endl;
}
  • 1024. 装箱问题

  • 只有已经被标记过的体积才能再填充减去再标记,最后找最小标记即可

#include<bits/stdc++.h>
using namespace std;
const int MAXV = 2e4 + 10;
bool dp[MAXV];
int main()
{
	int mi = MAXV;
	int v,n;cin >> v >> n;
	dp[v] = 1;
	for(int i = 1;i <= n;i++){
		int vv;cin >> vv;
		for(int j = vv;j <= v;j++)
			if(dp[j])
			{
				dp[j - vv] = 1;
				mi = min(j - vv,mi);
			}
	}
	cout << mi;
}

3.2二重01背包问题

  • 1022. 宠物小精灵之收服

  • 两个限制条件,就是加一重循环来更新,用两个数值代表现在状态

  • d p [ i ] [ j ] = m a x ( d p [ i ] [ j ] , d p [ i − t 1 ] [ j − t 2 ] + v ) dp[i][j]=max(dp[i][j],dp[i-t_1][j-t_2]+v) dp[i][j]=max(dp[i][j],dp[it1][jt2]+v)

  • 时间复杂度: O ( n m k ) O(nmk) O(nmk)

#include<bits/stdc++.h>
using namespace std;
pair<int,int> ans;
int dp[1001][501];
int main()
{
	int n,m,k;cin >> n >> m >> k;
	ans.first = 0,ans.second = m;
	for(int i = 1;i <= k;i++){
		int nu,at;cin >> nu >> at;
		for(int _i = 0;_i <= n - nu;_i++)
		for(int _j = 1;_j <= m - at;_j++)
		{
			dp[_i][_j] = max(dp[_i][_j],dp[_i + nu][_j + at] + 1);
			if(dp[_i][_j] > ans.first)
				ans = {dp[_i][_j],_i};
			else if(dp[_i][_j] == ans.first)
				ans.second = max(_j,ans.second);
		}
	}
	cout << ans.first << ' ' << ans.second;
}

3.3 01背包状态出现次数

  • 278. 数字组合

  • 设初始状态出现次数为1,更新背包时把更新前的出现次数加在更新后状态的出现次数

#include<bits/stdc++.h>
using namespace std;
int dp[10001];//出现次数
int main()
{
	int n,m;cin >> n >> m;
	dp[0] = 1;
	for(int i = 1;i <= n;i++){
		int x;cin >> x;
		for(int i = m;i >= x;i--)
			dp[i] += dp[i - x];
	}
	cout << dp[m];
}

3.4完全背包求方案数

  • 1023. 买书

  • 从前往后更新背包,这样就是完全背包,因为更新背包是更新后面,可以继续更新

#include<bits/stdc++.h>
using namespace std;
int dp[1001];//出现此数的数量
int num[] = {10,20,50,100};
int main()
{
	int n;cin >> n;
	dp[0] = 1;
	for(int i = 0;i < 4;i++)
	    for(int j = num[i];j <= n;j++)
	        dp[j] += dp[j - num[i]];
	cout << dp[n];
}
  • 1021. 货币系统 同理,记得开long long

3.5最少的数来组合出所有数

  • 532. 货币系统

  • 从小的开始,如果这个被标记过,就说明已经被其他数给表示了,否则就加入,进行一次完全背包

#include<bits/stdc++.h>
using namespace std;
const int MAXN = 101,MAXM = 2.5e4;
bool dp[MAXM];
int a[MAXN];
int main()
{
	int t;cin >> t;
	while(t--){
		int n;cin >> n;
		memset(dp,0,sizeof(dp));
		dp[0] = 1;
		for(int i = 1;i <= n;i++)
			cin >> a[i];
		sort(a + 1,a + 1 + n);
		int ans = 0;
		for(int i = 1;i <= n;i++){
			if(dp[a[i]])
				continue;
			ans++;
			for(int j = 0;j <= a[n] - a[i];j++)
				if(dp[j])
					dp[j + a[i]] = 1;
		}
		cout << ans << endl;
	}
}

3.6单调队列+滑动窗口+滚动数组 优化多重完全背包

  • 6. 多重背包问题 III

  • 现加入s个价值为w,体积为v的物体,那么能更新位置x的有

d p [ i ] [ x ] = m a x ( d p [ i − 1 ] [ x ] , d p [ i − 1 ] [ x − v ] + w , d p [ i − 1 ] [ x − 2 v ] + 2 w . . . , d p [ i − 1 ] [ x − s v ] + s w ) dp[i][x]=max(dp[i-1][x],dp[i-1][x-v]+w,dp[i-1][x-2v]+2w...,dp[i-1][x-sv]+sw) dp[i][x]=max(dp[i1][x],dp[i1][xv]+w,dp[i1][x2v]+2w...,dp[i1][xsv]+sw)

  • 那么更新位置x+v有

d p [ i ] [ x + v ] = m a x ( d p [ i − 1 ] [ x + v ] , d p [ i − 1 ] [ x ] + w , d p [ i − 1 ] [ x − v ] + w . . . , d p [ i − 1 ] [ x − ( s − 1 ) v ] + ( s − 1 ) w ) dp[i][x+v]=max(dp[i-1][x+v],dp[i-1][x]+w,dp[i-1][x-v]+w...,dp[i-1][x-(s-1)v]+(s-1)w) dp[i][x+v]=max(dp[i1][x+v],dp[i1][x]+w,dp[i1][xv]+w...,dp[i1][x(s1)v]+(s1)w)

  • 可以见到形式十分相似,我们可以使用滑动窗口来维护这个式子,利用单调队列来求出这个的最大值
  • 枚举所有v的余数即可
#include<bits/stdc++.h>
using namespace std;
const int MAXV = 2e4 + 10;
int dp[2][MAXV];
pair<int,int> deq[MAXV];
int main()
{
	int n,op = 0,V;cin >> n >> V;
	for(int i = 1;i <= n;i++){
		int v,w,s;cin >> v >> w >> s;
		
		for(int j = 0;j < v;j++)//枚举余数
		{
			int top = 1,end = 1;
			deq[1] = {0,0};
			for(int k = 1;k*v + j <= V;k++){
				while(top <= end && deq[end].first + (k - deq[end].second)*w < dp[1 - op][k*v + j])
					end--;
				deq[++end] = {dp[1 - op][k*v + j],k};
				if(k - deq[top].second > s)
					top++;
				dp[op][k*v + j] = deq[top].first + (k - deq[top].second)*w;
			}
		}
		op = 1 - op;
	}
	cout << dp[1 - op][V];
}

3.7简单的混合背包

  • 7. 混合背包问题

  • 如果是一次,就从后往前进行一次

  • 如果是完全就从前往后更新

  • 如果是多重就判断给的大小是否超过背包大小,如果超过就继续完全背包,否则就执行s次01背包

#include<bits/stdc++.h>
using namespace std;
int dp[1001];
int main()
{
	int n,V;cin >> n >> V;
	for(int i = 1;i <= n;i++){
		int v,w,s;cin >> v >> w >> s;
		if(s == 0 || v*s >= V){
			for(int k = v;k <= V;k++)
				dp[k] = max(dp[k],dp[k - v] + w);
		}
		else
		{
			s = max(s,1);
			for(int j = 1;j <= s;j++)
				for(int k = V;k >= v;k--)
					dp[k] = max(dp[k],dp[k - v] + w);
		}
	}
	cout << dp[V];
}

3.8二维费用背包

  • 8. 二维费用的背包问题

  • 就是加了1维,没什么差别

#include<bits/stdc++.h>
using namespace std;
int dp[101][101];
int main()
{
	int n,V,M;cin >> n >> V >> M;
	for(int i = 1;i <= n;i++){
		int v,m,w;cin >> v >> m >> w;
		for(int j = V;j >= v;j--)
		for(int k = M;k >= m;k--)
			dp[j][k] = max(dp[j][k],dp[j - v][k - m] + w);
	}
	cout << dp[V][M];
}

3.9满足条件或更好的最值背包

  • 1020. 潜水员
  • 每次找最优能更新此位置的位置
#include<bits/stdc++.h>
using namespace std;
int dp[80][22];
int main()
{
	int m,n;cin >> m >> n;
	int t;cin >> t;
	for(int i = 0;i <= m;i++)
	for(int j = 0;j <= n;j++)
		dp[j][i] = 1e9 + 10;
	dp[0][0] = 0;
	for(int i = 1;i <= t;i++){
		int a,b,c;cin >> a >> b >> c;
		for(int j = n;j >= 0;j--)
		for(int k = m;k >= 0;k--)
		{
			int aimj = max(0,j-b),aimk = max(0,k-a);
			dp[j][k] = min(dp[j][k],dp[aimj][aimk] + c);
		}
	}
	cout << dp[n][m];
}

3.10输出任意一种合法方案

  • 1013. 机器分配

  • 反向搜索,不用担心找不到,因为是一层一层推的,所以所有点都可以找到方案

#include<bits/stdc++.h>
using namespace std;
int dp[11][16];//给剩下的数量,执行了几个
int a[16][16];
void dfs(int n,int m){
	if(n == 1)
	{
		cout << 1 << ' ' << m << endl;
		return;
	}
	for(int i = 0;i <= m;i++){
		if(dp[n][m] == a[n][i] + dp[n - 1][m-i]){
			dfs(n-1,m-i);
			cout << n << ' ' << i << endl;
			return;
		}
	}
}
int main()
{
	int n,m;cin >> n >> m;
	for(int i = 1;i <= n;i++){
		for(int k = 0;k <= m;k++)
			dp[i][k] = dp[i - 1][k];
		for(int j = 1;j <= m;j++){
			cin >> a[i][j];
			for(int k = j;k <= m;k++)
				dp[i][k] = max(dp[i][k],dp[i - 1][k - j] + a[i][j]);
		}
	}
	cout << dp[n][m] << endl;
	dfs(n,m);
}

3.11有依赖的背包问题

  • 10.有依赖的背包问题

  • 先处理子节点,再处理父节点[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-hpsdLNZd-1688729665503)(C:\Users\Administrator\Desktop\markdown\有依赖的背包问题.png)]

#include<bits/stdc++.h>
using namespace std;
vector<int> son[101];
int dad[101];
int n,V,root;
int v[101],w[101];
int dp[2][101][101];
void dfs(int i){
	int op = 0;
	for(int j = v[i];j <= V;j++)
		dp[op][i][j] = dp[1 - op][i][j] = w[i];
	for(auto _i:son[i]){//更新所有子节点
		dfs(_i);
		op = 1 - op;
		for(int j = v[i];j <= V;j++)
			for(int k = 0;j - k >= v[i];k++)
				dp[op][i][j] = max(dp[op][i][j],max(dp[1-op][_i][k],dp[op][_i][k]) + dp[1-op][i][j - k]);
	}
}
int main()
{
	cin >> n >> V;
	for(int i = 1;i <= n;i++){
		cin >> v[i] >> w[i] >> dad[i];
		if(dad[i] == -1){
			root = i;
			continue;
		}
		son[dad[i]].push_back(i);
	}
	dfs(root);
	cout << max(dp[0][root][V],dp[1][root][V]);
}
  • 分组背包就是一组内只能取一种状态,所以我们记录更新前的背包,对这组数据用更新前的背包更新新背包,这样就不会使数据重复更新,一般用滚动数组实现

3.12背包问题求方案数

  • 11. 背包问题求方案数

  • 更新就替换方案数,相同就加上,最后统计时有可能体积不同但是最大值一样

#include<bits/stdc++.h>
using namespace std;
#define ll long long
const int mod = 1e9 + 7;
const int MAXV = 1e3 + 10;
bool able[MAXV];
pair<ll,ll> dp[MAXV];
int main()
{
	able[0] = 1;
	dp[0].second = 1;
	int n,v;cin >> n >> v;
	for(int i = 1;i <= n;i++){
		int _v,_w;cin >> _v >> _w;
		for(int j = v;j >= _v;j--){
			if(able[j - _v])
			{
				if(dp[j - _v].first + _w > dp[j].first)
				{
					dp[j].first = dp[j - _v].first + _w;
					dp[j].second = dp[j - _v].second;
					able[j] = 1;
				}
				else if(dp[j - _v].first + _w == dp[j].first){
					dp[j].second = (dp[j].second + dp[j - _v].second) % mod;
				}
			}
		}
	}
	ll num = 0;
	ll ma = 0;
	for(int i = v;i >= 0;i--){
		if(able[i]){
			if(dp[i].first > ma){
				ma = dp[i].first;
				num = dp[i].second;
			}
			else if(dp[i].first == ma){
				num = (num + dp[i].second) % mod;
			}
		}
	}
	cout << num << endl;
}

3.13背包问题求具体方案

  • 12. 背包问题求具体方案

  • 要字典树最小的具体方案,那么较小的必须先判断能否取到最大的方案,那么就要让它最后更新背包,标记这个体积下能否用它更新背包,说明可以取

#include<bits/stdc++.h>
using namespace std;
const int MAXN = 1e3 + 10;
int dp[MAXN][MAXN];
int v[MAXN],w[MAXN];
bool able[MAXN][MAXN];
int main()
{
	int n,V;cin >> n >> V;
	for(int i = 1;i <= n;i++)
	{
		cin >> v[i] >> w[i];
	}
	for(int i = n;i >= 1;i--){
		for(int j = 1;j <= V;j++){
			dp[i][j] = dp[i + 1][j];//先不取
			if(j >= v[i] && dp[i][j] <= dp[i + 1][j - v[i]] + w[i])
			{
				able[i][j] = 1;
				dp[i][j] = dp[i + 1][j - v[i]] + w[i];
			}
		}
	}
	int now = V;
	for(int i = 1;i <= n;i++){
		if(able[i][now])//能取
		{
			cout << i << ' ';
			now -= v[i];
		}
	}
}

3.14贪心确定顺序后背包

  • 734. 能量石

  • 假设最优解为 p 1 , p 2 , p 3 . . . p_1,p_2,p_3... p1,p2,p3...那么无论如何交换最优解的顺序都不能让答案变大,所以我们可以用贪心先确定这个顺序,然后用背包确定哪些取,那些不取

#include<bits/stdc++.h>
using namespace std;
const int MAXN = 101,MAXS = 1e4;
struct rock{
	int s,e,l;
}r[MAXN];
bool cmp(rock a,rock b){
	return a.e + b.e - b.l*a.s > b.e + a.e - b.s*a.l;
}
int dp[MAXS];
int main()
{
	int t;cin >> t;
	int ptop=1;
	while(t--){
		memset(dp,0,sizeof(dp));
		int n;cin >> n;
		for(int i = 1;i <= n;i++){
			cin >> r[i].s >> r[i].e >> r[i].l;
		}
		sort(r + 1,r + 1 + n,cmp);
		int ma = 0;
		for(int i = 1;i <= n;i++){
			for(int j = MAXS - 1;j >= r[i].s;j--){
				dp[j] = max(dp[j],dp[j - r[i].s] + r[i].e - r[i].l*(j - r[i].s));
				ma = max(dp[j],ma);
			}
		}
		cout << "Case #" << ptop << ": " << ma << endl;
		ptop++;
	}
}

4.状态机

  • 将状态转换为特定的数字,根据状态之间的转换来确定

  • 1049. 大盗阿福

  • 设偷这个店的状态为1,不偷为0,就有状态转换:不偷可以由偷和不偷转移,偷只能由不偷转移

  • d p [ i ] [ 0 ] = m a x ( d p [ i − 1 ] [ 1 ] , d p [ i − 1 ] [ 0 ] ) dp[i][0]=max(dp[i-1][1],dp[i-1][0]) dp[i][0]=max(dp[i1][1],dp[i1][0])

  • d p [ i ] [ 1 ] = d p [ i − 1 ] [ 0 ] + w dp[i][1]=dp[i-1][0]+w dp[i][1]=dp[i1][0]+w

#include<bits/stdc++.h>
using namespace std;
const int MAXN = 1e5 + 10;
int dp[MAXN][2];
int main(){
	int t;cin >> t;
	while(t--){
		memset(dp,0,sizeof(dp));
		int n;cin >> n;
		for(int i = 1;i <= n;i++){
			int v;cin >> v;
			dp[i][1] = dp[i - 1][0] + v;
			dp[i][0] = max(dp[i - 1][0],dp[i - 1][1]);
		}
		cout << max(dp[n][0],dp[n][1]) << endl;
	}
}
  • 1057. 股票买卖 IV

  • 假设持有股票为1,没有为0,就有 d p [ 第几个 ] [ 交易了几轮 ] [ 是否有股票 ] dp[第几个][交易了几轮][是否有股票] dp[第几个][交易了几轮][是否有股票]

  • d p [ i ] [ j ] [ 0 ] = m a x ( d p [ i − 1 ] [ j − 1 ] [ 1 ] + v , d p [ i − 1 ] [ j ] [ 0 ] ) dp[i][j][0]=max(dp[i-1][j-1][1]+v,dp[i-1][j][0]) dp[i][j][0]=max(dp[i1][j1][1]+v,dp[i1][j][0])

  • d p [ i ] [ j ] [ 1 ] = m a x ( d p [ i − 1 ] [ j ] [ 0 ] − v , d p [ i − 1 ] [ j ] [ 1 ] ) dp[i][j][1]=max(dp[i-1][j][0]-v,dp[i-1][j][1]) dp[i][j][1]=max(dp[i1][j][0]v,dp[i1][j][1])

  • 还能用滚动数组优化

#include<bits/stdc++.h>
using namespace std;
const int MAXN = 1e5 + 10;
int dp[2][101][2];
int main()
{
	int n,k;cin >> n >> k;
	int op = 0;
	for(int i = 0;i <= 1;i++)
	for(int j = 0;j <= k;j++)
	dp[0][j][i] = dp[1][j][i] = -1e9;
	for(int j = 0;j <= k;j++)
		dp[0][j][0] = dp[0][j][1] = 0;//初始状态
	int ma = 0;
	for(int i = 1;i <= n;i++){
		int v;cin >> v;
		for(int j = k - 1;j >= 0;j--){
			dp[0][j + 1][1 - op] = max(dp[0][j + 1][op],dp[1][j][op] + v);
			ma = max(dp[0][j + 1][1 - op],ma);
			dp[1][j][1 - op] = max(dp[1][j][op],dp[0][j][op] - v);
		}
		op = 1 - op;
	}
	cout << ma << endl;
}
  • 1058. 股票买卖 V

  • 多了一个冷却状态2

  • d p [ i ] [ j ] [ 2 ] = d p [ i − 1 ] [ j ] [ 1 ] dp[i][j][2]=dp[i-1][j][1] dp[i][j][2]=dp[i1][j][1]

  • d p [ i ] [ j ] [ 1 ] = m a x ( d p [ i − 1 ] [ j − 1 ] [ 0 ] + w , d p [ i − 1 ] [ j ] [ 1 ] ) dp[i][j][1]=max(dp[i-1][j-1][0]+w,dp[i-1][j][1]) dp[i][j][1]=max(dp[i1][j1][0]+w,dp[i1][j][1])

  • d p [ i ] [ j ] [ 0 ] = m a x ( d p [ i − 1 ] [ j ] [ 0 ] , d p [ i − 1 ] [ j ] [ 2 ] ) dp[i][j][0]=max(dp[i-1][j][0],dp[i-1][j][2]) dp[i][j][0]=max(dp[i1][j][0],dp[i1][j][2])

#include<bits/stdc++.h>
using namespace std;
const int MAXN = 1e5 + 10;
int dp[3][2];//0无,1有,2冷却
int main()
{
	int n,op = 0;cin >> n;
	dp[1][1] = dp[1][0] = dp[2][1] = dp[2][0] = -1e9;//不存在
	for(int i = 1;i <= n;i++){
		int x;cin >> x;
		dp[0][op] = max(dp[2][1 - op],dp[0][1 - op]);
		dp[1][op] = max(dp[0][1 - op] - x,dp[1][1 - op]);
		dp[2][op] = dp[1][1 - op] + x;
		op = 1 - op;
	}
	cout << max(dp[0][1 - op],dp[2][1 - op]);
}

其他

最大k块连续序列之和

  • A - Max Sum Plus Plus

  • d p [ 2 ] [ N ] dp[2][N] dp[2][N],第一个参量表示是否取了上一个数,第二个参量表示是否取了多少块,本身代表和

#include<bits/stdc++.h>//
using namespace std;

#define ll long long 
inline int read() {
    int X=0,w=1; int c=getchar();
    while (c<'0'||c>'9') { if (c=='-') w=-1; c=getchar(); }
    while (c>='0'&&c<='9') X=(X<<3)+(X<<1)+(c^48),c=getchar();
    return X*w;
}
inline void write(ll x)
{
    if(x<0){
    	putchar('-');
		x=-x;
	}
    if(x>9) 
		write(x/10);
    putchar(x%10+'0');
}

const int N = 1e6 + 10,inf = 1e9 + 10;
int dp[N];
int ma[N];
int a[N];

int main(){
	int m,n;
	while(~scanf("%d %d",&m,&n)){
		for(int i = 1;i <= n;i++)
			a[i] = read();
		memset(dp,0,sizeof(dp));dp[0] = -inf;
		memset(ma,0,sizeof(ma));
		int maa;
		for(int i = 1;i <= m;i++){
			maa = -inf;
			for(int j = 1;j <= n;j++){
				dp[j] = max(dp[j - 1] + a[j],ma[j - 1] + a[j]);
				ma[j - 1] = maa;
				maa = max(dp[j],maa);
			}
		}
		printf("%d\n",maa);
	}
}

单调栈求最大可行矩形

  • 二维H - 棋盘制作

  • 一维Largest Rectangle in a Histogram

  • 对于一个大矩形中有一些点不可行,然后要求最大可行矩形问题,用单调栈解决

  • 栈内元素单调递增,如果遇到小的数,说明栈顶的元素无法向右继续延伸了,用现在的位置减去它的左边界就是最大的宽度

  • 同时距离去掉的最左边边界,这就是新元素的左边界了(去掉的都比新元素大)

#include<bits/stdc++.h>
using namespace std;
#define ll long long
const int N = 1e5 + 10;
ll w[N],a[N];
int main(){
    ios::sync_with_stdio(false);//写了using namespace std;
    ll n;cin >> n;
    while(n){
        stack<pair<ll,ll>> st;
        ll ma = 0;
        for(int i = 1;i <= n;i++){
            ll x;cin >> x;
            ll l = i;
            while(!st.empty() && x < st.top().first){
                ma = max(ma,(i - st.top().second)*st.top().first);
                l = min(st.top().second,l);
                st.pop();
            }
            st.push({x,l});
        }
        while(!st.empty()){
            ma = max(ma,(n + 1 - st.top().second)*st.top().first);
            st.pop();
        }
        cout << ma << endl;
        cin >> n;
    }
}
#include<bits/stdc++.h>
using namespace std;
#define int long long
int n,m;
const int N = 2e3 + 10;
bool mp[N][N];
int dp[2][N][N];
int a[N];
signed main(){
	ios::sync_with_stdio(false);//写了using namespace std;
	cin >> n >> m;
	for(int i = 1;i <= n;i++)
	for(int j = 1;j <= m;j++){
		cin >> mp[i][j];
		mp[i][j] ^= ((i + j) % 2);
	}
	int ma1 = 0,ma2 = 0;
	bool f = 1;
	for(int i = 1;i <= n;i++){
		for(int j = 1;j <= m;j++){
			if(mp[i][j])
				dp[1][i][j] = dp[1][i - 1][j] + 1;
			else
				dp[0][i][j] = dp[0][i - 1][j] + 1;
		}
		stack<pair<int,int>> st;
		for(int j = 1;j <= m;j++){
			int l = j;
			while(!st.empty() && dp[1][i][j] < st.top().first){
				int wid = j - st.top().second;
				int h = st.top().first;
				ma1 = max(min(h,wid)*min(h,wid),ma1);
				ma2 = max(h*wid,ma2);
				l = st.top().second;
				st.pop();
			}
			st.push({dp[1][i][j],l});
		}
		while(!st.empty()){
			int wid = m + 1 - st.top().second;
			int h = st.top().first;
			ma1 = max(min(h,wid)*min(h,wid),ma1);
			ma2 = max(h*wid,ma2);
			st.pop();
		}
		for(int j = 1;j <= m;j++){
			int l = j;
			while(!st.empty() && dp[0][i][j] < st.top().first){
				int wid = j - st.top().second;
				int h = st.top().first;
				ma1 = max(min(h,wid)*min(h,wid),ma1);
				ma2 = max(h*wid,ma2);
				
				l = st.top().second;
				st.pop();
			}
			st.push({dp[0][i][j],l});
		}
		while(!st.empty()){
			int wid = m + 1 - st.top().second;
			int h = st.top().first;
			ma1 = max(min(h,wid)*min(h,wid),ma1);
			ma2 = max(h*wid,ma2);
			st.pop();
		}
	}
	cout << ma1 << endl << ma2 << endl;
}

最长相同子序列

  • L - Common Subsequence
  • d p [ i ] [ j ] dp[i][j] dp[i][j]第一个字符串枚举到那里,第二个,记录长度
#include<bits/stdc++.h>
using namespace std;
const int N = 1e3 + 10;

int dp[N][N];

int main()
{
	string s1,s2;
	while(cin >> s1 >> s2){
		int n = s1.size(),m = s2.size();
		memset(dp,0,sizeof(dp));
		s1 = ' ' + s1,s2 = ' ' + s2;
		for(int j = 1;j <= n;j++)
			for(int k = 1;k <= m;k++){
				if(s1[j] == s2[k]){
					dp[j][k] = dp[j - 1][k - 1] + 1;
				}else{
					dp[j][k] = max(dp[j - 1][k],dp[j][k - 1]);
				}
			}
		cout << dp[n][m] << endl;
	}
	
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/728489.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

mybatis-plus记录

1. 导入依赖 注意&#xff1a;springboot和mybatisplus的版本必须一致 导入build工具 <build><plugins><!-- 具体插件&#xff0c;逆向工程的操作是以构建过程中插件形式出现的 --><plugin><groupId>org.mybatis.generator</groupId>&l…

微信视频号配合OBS拉流推流开直播

背景 公司有要求&#xff0c;要实现外部视频流的同步直播&#xff0c;所以特意研究了一下OBS软件结合微信视频号直播的操作步骤。 一、OBS软件配置 &#xff08;一&#xff09;配置拉流 启动OBS软件-点击“”-选择增加“媒体源” 创建源名称 取消本地文件-填写拉流地址-…

MFC List Control控件添加单元格编辑和单元格下拉列表

文章目录 初始化编译栏的创建与销毁下拉列表的创建与销毁自定义编译栏与下拉框的焦点问题点击CListCtrl 事件处理程序双击添加全部代码 ui 设置 初始化 #define IDC_EDIT_CREATEID 3000 #define IDC_COMBOX_CREATEID 3001int e_Item0; //刚编辑的行 int e_SubItem2; //刚…

导入数据解析

Before未定义异常情况 继承 AnalysisEventListener 重写 onException Overridepublic void onException(Exception exception, AnalysisContext context) throws Exception {if (exception instanceof ExcelDataConvertException) {ExcelDataConvertException excelDataConvert…

Django的数据库模型迁移命令makemigrations和migrate是否会导致数据库中的数据丢失?

我们知道&#xff0c;如果在Django的文件models.py中写好了数据库模型&#xff0c;要生成对应的数据库&#xff0c;需要执行下面两条命令&#xff1a; python manage.py makemigrations python manage.py migrate其中命令 makemigrations 是生成迁移执行文件&#xff0c;命令 …

tortoiseGit fatal: Could not read from remote repository.

1、问题场景&#xff1a; 使用tortoiseGit工具pull代码的时候报错 git.exe pull --progress -v --no-rebase "origin" fatal: Could not read from remote repository. Please make sure you have the correct access rights and the repository exists. 无法从存…

投票管理平台达到投票平台投票平台平台投票

现在来说&#xff0c;公司、企业、学校更多的想借助短视频推广自己。 通过微信投票小程序&#xff0c;网友们就可以通过手机拍视频上传视频参加活动&#xff0c;而短视频微信投票评选活动既可以给用户发挥的空间激发参与的热情&#xff0c;又可以让商家和企业实现推广的目的&am…

基于图的路径规划算法对比

基于图的路径规划算法对比 算法说明与实现效果构造路网路网数据转化为图matlab代码 算法说明与实现效果 通过构造邻接矩阵&#xff0c;在构造的路网中找到一个节点通向另一个节点的最短路径&#xff0c;包括DJ&#xff0c;Floyd&#xff0c;A*&#xff0c;ACO&#xff0c;GA算…

以阻塞方式对IO文件进行读取

以阻塞方式对IO文件进行读取(test.c读取&#xff0c;test2.c发送数据) 实验结果 执行test.c生成的pro1可执行文件&#xff0c;光标显示处于阻塞状态 执行test2.c生成的pro2可执行文件&#xff0c;test.c处打印 hello dhl 三级标题test.c #include <stdlib.h> #inclu…

【Leetcode】209. 长度最小的子数组

给定一个含有 n 个正整数的数组和一个正整数 s &#xff0c;找出该数组中满足其和 ≥ s 的长度最小的 连续 子数组&#xff0c;并返回其长度。如果不存在符合条件的子数组&#xff0c;返回 0。 示例&#xff1a; 输入&#xff1a;s 7, nums [2,3,1,2,4,3] 输出&#xff1a;…

干货满满!阿里、京东、网易等多位专家力荐的高并发编程速成笔记

前一段时间在某乎看到一个提问&#xff0c;说的是他才一年半经验&#xff0c;去面试却被各种问到分布式、高并发、多线程之间的问题。基础层面上的是可以答上来&#xff0c;但是面试官深问的话就不会了&#xff01;被问得都怀疑现在Java招聘初级岗位到底招的是初级开发还是架构…

7-7作业

发送端 #include<stdio.h> #include<Windows.h> #include<windows.h> #include<WinSock2.h> #include<string.h> #include<stdlib.h> #define ERR_OR(msg) do{\ fprintf(stderr, "__%d__", __LINE__);\ perror(msg);\ }while(0…

用Python爬取电影数据并可视化分析

&#x1f935;‍♂️ 个人主页&#xff1a;艾派森的个人主页 ✍&#x1f3fb;作者简介&#xff1a;Python学习者 &#x1f40b; 希望大家多多支持&#xff0c;我们一起进步&#xff01;&#x1f604; 如果文章对你有帮助的话&#xff0c; 欢迎评论 &#x1f4ac;点赞&#x1f4…

simulink m脚本管理模型参数

clear; m 1600;%kg 默认都是double g 9.8;% m/s^2 f 0.015;%滚动阻力系数 Cd 0.3;%空气阻力系数 A 2;%m^2 delta 1.2;% 旋转质量换算系数 alpha 0;%坡度 rad 脚本写完一定要运行&#xff0c;等右侧工作区加载完成

酷瓜云课堂(企业版)v1.2.1 发布,网课网校系统,持续更新

更新内容 增加开票额度收支逻辑使用本地图像验证码升级layui-v2.8.8优化钉钉webhook优化队列处理任务优化migrations文件修正提现平台检查修正移动端配置项为空异常调整UserBalance属性 注意事项 如果你的起始版本 > v1.2.0&#xff0c;请忽略以下操作&#xff0c;按照正…

窥探广告公司内幕:揭秘部门运作方式

一般的广告公司大概可以分为三大部门&#xff1a;1、创作部(Creative)、2、客户服务部(Account Servicing)、3、媒介部(Media)。 1、创作部(Creative Department) 创作部的主要工作是负责构思广告及执行广告创作。重心人物是行政创作总监(Executive Creative Director, ECD)。…

Openmediavault配置存储网盘的 用户、组、权限、共享+文档访问功能 (续debian Linux安装配置企业私有网盘)

一、适用环境 1、使用专业服务器的存储容量保存教学资源、企业资源&#xff0c;可供有权限用户共享读取访问。 2、需要对批量的用户进行管理&#xff0c;不同的用户属于不同的组&#xff0c;不同组具备不同的访问权限&#xff0c;如&#xff1a;有些用户只需要读取打开执行&am…

Vue实现在线文档预览

目录 背景在线预览Office文档文件在线预览pdf文档预览方案一方案二 Word文档预览Excel文档预览PPT文档预览 纯文本、各种代码文件预览图片文件预览视频文件预览Aliplayer阿里云播放器Xgplayer西瓜播放器Bilibiliplayer仿哔哩哔哩弹幕播放器 音频文件预览在线文档预览项目&#…

(vue)人工智能,区分对话框各自内容区域样式

(vue)人工智能&#xff0c;区分对话框各自内容区域样式 效果&#xff1a; 思路&#xff1a; 1.一行里包含 对方头像、内容、我方头像 三部分 2.根据消息数组的下标&#xff0c;确定是我方消息还是对方消息&#xff08;偶数我方&#xff0c;奇数对方&#xff09; 3.根据奇偶数显…

MapStruct转换时的一些问题

1.当属性名相同 类型不同时&#xff0c;需要手动指明映射 Mappings({Mapping(source "customerType",target "customerType"),Mapping(source "customerStatus",target "customerStatus"))List<CustomerBindDetailExcelVO> …