牛客小白月赛34

https://ac.nowcoder.com/acm/contest/11211#question

a题
在这里插入图片描述
思路:
两种方法
① 找最长上升子序列,那剩下的那些就是要修改的,O(nlogn)
② f[ i ][ j ] 代表 修改到第i位,最后一位<=j的最小代价。
转移方程:f[ i ][ j ] = min(f[ i ][ j-1 ],f[ i - 1][ j ] + (a[i] != (j - 1 + ‘A’))); O(26 * n)

int t,n,m;
char s[N],a[N];
int main(){
    scanf("%d",&n);
    getchar();
    scanf("%s",s+1);
    a[1] = s[1];
    int cnt = 1;
    for(int i=2;i<=n;i++){
        if(s[i] >= a[cnt]) a[++cnt] = s[i];
        else{
            int pos = upper_bound(a+1,a+1+cnt,s[i]) - a;
            a[pos] = s[i];
        }
    }
    printf("%d\n", n - cnt);
    return 0;
}
int t,n,m;
char s[N],a[N];
int f[N][30];
int main(){
    cin>>n;
    cin>>a + 1;
    memset(f,0x3f,sizeof f);
    for(int i=1;i<=26;i++) f[0][i] = 0;
    for(int i=1;i<=n;i++){
        for(int j=1;j<=26;j++){
            f[i][j] = min(f[i][j-1],f[i-1][j] + (a[i] != (j - 1 + 'A')));
        }
    }
    cout<<f[n][26]<<endl;
    return 0;
}

b题
在这里插入图片描述
思路:
状压dp
每个点只有经过和没经过两个状态
f [ i ] [ j ] [ k ] ,i 表示二进制所有的状态,j表示当前停在哪个点, k取值0,1,2,3
k = 0 代表 没有经过重力和反重力
k = 1 代表 经过重力加速
k = 2 代表 经过反重力加速
k = 3 代表 两个加速都用过了

转移方程:
在这里插入图片描述
到状态0,原值 与 这次跳 取min
到状态1,分为这次用了重力加速 和 之前用的重力加速 ,与 原值取min
到状态2,分为这次用了反重力加速 和 之前用的反重力加速 , 与原值取min
到状态3,分为 状态1用了反重力加速 ;状态2用了重力加速;状态3正常跳;与原值取min


const int N = 70000,M = 20;
int f[N][M][5];
int n;
int p[M][M];
int a[M],b[M],c[M];
int main(){
	cin>>n;
	for(int i=1;i<=n;i++)
		for(int j=1;j<=n;j++)
			cin>>p[i][j];
	memset(f,0x3f,sizeof f);
	for(int i=0;i<n;i++) f[1<<i][i+1][0] = 0;
	for(int op=1;op<(1<<n);op++){
		int cnt1=0,cnt2=0;
		for(int i=1;i<=n;i++){
			if(op >> (i-1) & 1) a[++cnt1] = i;
			else b[++cnt2] = i; 
		}
		for(int i=1;i<=cnt1;i++){
			for(int j=1;j<=cnt2;j++){
				f[op + (1 << (b[j] - 1))][b[j]][0] = min(f[op + (1 << (b[j] - 1))][b[j]][0],f[op][a[i]][0] + p[a[i]][b[j]]);
				f[op + (1 << (b[j] - 1))][b[j]][1] = min(f[op + (1 << (b[j] - 1))][b[j]][1],min(f[op][a[i]][0],f[op][a[i]][1] + p[a[i]][b[j]]));
				f[op + (1 << (b[j] - 1))][b[j]][2] = min(f[op + (1 << (b[j] - 1))][b[j]][2],min(f[op][a[i]][0] + 2 * p[a[i]][b[j]],f[op][a[i]][2] + p[a[i]][b[j]]));
				f[op + (1 << (b[j] - 1))][b[j]][3] = min(min(f[op + (1 << (b[j] - 1))][b[j]][3],f[op][a[i]][3] + p[a[i]][b[j]]),min(f[op][a[i]][2],f[op][a[i]][1] + 2 * p[a[i]][b[j]]));
			}
		}
	}
	int res = 0x3f3f3f3f;
	for(int i=1;i<=n;i++)
		res = min(res,f[(1<<n) - 1][i][3]);
	cout<<res<<endl;
	return 0;
}

c题
在这里插入图片描述
思路:
与a题的做法二类似,
改一下转移方程就好了,加上偏移量
f [ i ] [ j ] = min(f [ i ] [ j - 1] , f [ i - 1] [ j ] + abs(a[ i ] - (j + 1 - ‘A’));

const int N = 1000010, M = 30;
char a[N];
int n;
ll f[N][M];
int main(){
	cin>>n;
	cin>>a + 1;
	memset(f,0x3f,sizeof f);
	for(int i=1;i<=26;i++) f[0][i] = 0;
	
	for(int i=1;i<=n;i++){
		for(int j=1;j<=26;j++){
			f[i][j] = min(f[i][j-1],f[i-1][j] + abs(a[i] - (j - 1 + 'A')));
		}
	}
	cout<<f[n][26]<<endl;
	return 0;
} 

d题
在这里插入图片描述
思路:
这题虽然过的人比g,h多,但我看题解的时候,理解花的时间比g和更久。。

考虑只有两行的时候,分别对两行进行降序排列,
那比如当前取了a[2] + b[3] ,那就往优先队列里放a[3]+b[2],a[2]+b[4],
思考一下这样的过程,会出现很多重复的。
如果是一开始将一维里所有的放进去,之后只要插入另一维就好了
多行也同理,每次将当前行 和 已经搞好的n个最大的数的合成行 进行合并
在这里插入图片描述

#include<bits/stdc++.h>
using namespace std;
const int N = 510;
int n;
int a[N],b[N];
struct node{
	int va,id;
	bool operator<(const node &t)const{
		return va < t.va;
	}
};
priority_queue<node> q;
int main(){
	cin>>n;
	for(int i=1;i<=n;i++) cin>>b[i];
	sort(b+1,b+1+n,greater<int>());
	for(int i=2;i<=n;i++){
		for(int j=1;j<=n;j++) cin>>a[j];
		sort(a+1,a+1+n,greater<int>());
		for(int j=1;j<=n;j++){
			q.push({a[1] + b[j],1});
		}
		for(int j=1;j<=n;j++){
			node t = q.top();q.pop();
			b[j] = t.va;
			q.push({t.va - a[t.id] + a[t.id+1],t.id+1});
		}
		while(q.size()) q.pop();
	}	
	for(int j=1;j<=n;j++) cout<<b[j]<<" ";
	return 0;
}

g题
在这里插入图片描述
思路:
按照题意思考,
任意大于2的子串都不是回文串,
如果子串的长度为偶数,则相邻两位不同
如果子串的长度为奇数,则当前位前后两位不同即可满足
如果每次枚举三位,则是 O(n * 26 ^ 3) 复杂度,太大了
考虑鸽巢原理,每一位只受前2位和后2位的影响,5种情况必有一种可以满足
所以枚举改变量即可。
f [ i ] [ y ] [ z ] 代表当前枚举到第i位,第i-1位的改变量是y,第i位的改变量是z的最小代价
f [ i ] [ y ] [ z ] = min(f [ i ] [ y ] [ z ] , f [ i - 1] [ x ] [ y ] + abs(z));

//g题 

const int N = 1000010,M = 6;
char s[N];
int f[N][M][M];
int a[N],n;
int main(){
	cin>>n;
	cin>>s + 1;
	for(int i=1;i<=n;i++) a[i] = s[i] - 'a';
	memset(f,-1,sizeof f);
	
	for(int i=-2;i<=2;i++)
		for(int j=-2;j<=2;j++)
			if((a[1] + i + 26) % 26 != (a[2] + j + 26) % 26) 
				f[2][i + 2][j + 2] = abs(i) + abs(j); 
	
	for(int i=3;i<=n;i++)
		for(int x = -2;x <= 2;x ++)
			for(int y = -2; y <= 2; y ++)
				if(f[i-1][x + 2][y + 2] != -1)
					for(int z = -2;z <= 2;z ++)
						if((a[i] + z + 26) % 26 != (a[i-2] + x + 26) % 26 && (a[i] + z + 26) % 26 != (a[i-1] + y + 26) % 26)
							if(f[i][y + 2][z + 2] == -1) 
								f[i][y + 2][z + 2] = f[i-1][x + 2][y + 2] + abs(z);
							else  
								f[i][y + 2][z + 2] = min(f[i][y + 2][z + 2],f[i-1][x + 2][y + 2] + abs(z));

	int res = 2e9;
	for(int i=0;i<=4;i++)
		for(int j=0;j<=4;j++)
			if(f[n][i][j] != -1) res = min(res,f[n][i][j]);
	cout<<res<<endl;
	
	return 0;
} 

h题
在这里插入图片描述
思路:
无论如何,位置 i %(k + 1) 余数相同的这些位上的这些数都应该一样
枚举a,取min
%(k+1) 余数一样的这些位,a = 这些位里的最小值,b = 全局最小值(因为a >= b)(因为只能减)

res = min(res , 是a的这些位之和 - 是a 的这些位中的最小值 * 是a的这些位的个数 + 是b的这些位之和 - 全局最小值 * 是b 的这些位的个数);

const int N = 1e6+10;
int n,k;
ll a[N],cnt[N],va[N],nowmin[N];
int main(){
	scanf("%d%d",&n,&k);	
	for(int i=1;i<=n;i++) scanf("%lld",&a[i]);
	k++;
	ll sum = 0,mins = 0x3f3f3f3f;
	memset(nowmin,0x3f,sizeof nowmin);
	for(int i=1;i<=n;i++) {
		va[i % k] += a[i];
		cnt[i % k]++;
		nowmin[i % k] = min(nowmin[i % k],a[i]);
		sum += a[i];
		mins = min(mins,a[i]);
	}
	ll res = 2e18;
	for(int i = 0 ;i < k;i++){
		res = min(res,va[i] - nowmin[i] * cnt[i] + sum - va[i] - mins * (n - cnt[i]));
	}
	printf("%lld\n",res);
	return 0;
} 
标题“51单片机通过MPU6050-DMP获取姿态角例程”解析 “51单片机通过MPU6050-DMP获取姿态角例程”是一个基于51系列单片机(一种常见的8位微控制器)的程序示例,用于读取MPU6050传感器的数据,并通过其内置的数字运动处理器(DMP)计算设备的姿态角(如倾斜角度、旋转角度等)。MPU6050是一款集成三轴加速度计和三轴陀螺仪的六自由度传感器,广泛应用于运动控制和姿态检测领域。该例程利用MPU6050的DMP功能,由DMP处理复杂的运动学算法,例如姿态融合,将加速度计和陀螺仪的数据进行整合,从而提供稳定且实时的姿态估计,减轻主控MCU的计算负担。最终,姿态角数据通过LCD1602显示屏以字符形式可视化展示,为用户提供直观的反馈。 从标签“51单片机 6050”可知,该项目主要涉及51单片机和MPU6050传感器这两个关键硬件组件。51单片机基于8051内核,因编程简单、成本低而被广泛应用;MPU6050作为惯性测量单元(IMU),可测量设备的线性和角速度。文件名“51-DMP-NET”可能表示这是一个与51单片机及DMP相关的网络资源或代码库,其中可能包含C语言等适合51单片机的编程语言的源代码、配置文件、用户手册、示例程序,以及可能的调试工具或IDE项目文件。 实现该项目需以下步骤:首先是硬件连接,将51单片机与MPU6050通过I2C接口正确连接,同时将LCD1602连接到51单片机的串行数据线和控制线上;接着是初始化设置,配置51单片机的I/O端口,初始化I2C通信协议,设置MPU6050的工作模式和数据输出速率;然后是DMP配置,启用MPU6050的DMP功能,加载预编译的DMP固件,并设置DMP输出数据的中断;之后是数据读取,通过中断服务程序从DMP接收姿态角数据,数据通常以四元数或欧拉角形式呈现;再接着是数据显示,将姿态角数据转换为可读的度数格
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值