杭银理财杯第二题(暴搜)虽然时间超限未过,求优化建议

        题目大意:对A和B序列进行如题二三行操作,至少需要多少次可以使A+B=C。(第一行,第二行,第三行)

        思路:先创建一个三行n列的数组a[3][n]。然后创建一个b[N]数组,用来储存a[2][i]-a[1][i]的数据(第三行的数据减去第二行的对应数据),然后和a[1][i]比较。定义op(对第二行操作的次数)定义op2(对第一行操作的次数)。对第二行操作(可理解为转动第二行,就像密码箱的密码锁一样),然后每操作一次就让第三行减去第二行,再将结果和第一行进行对比,如果不行就对第一行操作(最多转n次,因为第n次的时候就恢复到原样了)。如果n次对第一行操作之后仍然无法配对,就对第二行进行下一轮操作。如果行,就输出对第一行的操作数和对第二行的操作数(也就是op+op2),如果都不行,那就输出-1

        因为题目条件限制有A,B,C中的元素都大于1,所以当b[i]<=0时直接排除,然后对第二行再进行操作。如果这些元素都>=1,就开始和第一行进行比较。

        这里用num来做计数器(有配对的就num++,否则重置num=0,如果num==n-1,就说明b数组和第一行全部配对,就说明条件成立,flag=1。输出op+op2) 

           每一次对第一行操作都会op2++。

        用h作为b数组的下标,(z+op2)%n来表示对第一行操作后的各元素下标,如果不符合,同样h和z重置为0。

        时间复杂度大概是3*n+n^3,好像quo实有点大了,救救阔怜的大一孩子叭T^T

​#include<bits/stdc++.h>
using namespace std;
const int N = 1e5 + 10;
int a[3][N];
int b[N];
int main() {
	int n;
	cin >> n;
	int i, j,op=0,k,op2=0;//op为对第二行操作次数,op2为对第一行操作次数
	int flag;//标志变量,1代表符合条件,0代表不符合
	for (i = 0; i < 3; i++) {
		for (j = 0; j < n; j++) cin >> a[i][j];
	}//输入数据
	for (j = 0; j < n; j++) {
		flag = 1;
		for (i = 0; i < n; i++) {//算出b[i]
			b[i] = a[2][i] - a[1][i];
			if (b[i] <= 0) {
				flag = 0;
				break;
			}//如果某一项<=0 退出,直接进入下一轮,对第二行进行操作(可降低时间复杂度)
		}
		if (flag == 0) {
			int t = a[1][0];//保存第一个元素
			for (i = 0; i < n - 1; i++) {
				a[1][i] = a[1][i + 1];
			}//所有的数据都往前移动
			a[1][n - 1] = t;//让最后一个数据变成原数组的第一个数据
			op++;//对第二行的操作次数增加
			continue;//跳到下一组(下面的所有程序不执行,直接进入下一组(剪枝)
		}//转动第二行
		else {	
			op2 = 0;//操作第一行的次数
			int	h=0,z=0,num=0;
			while (op2 < n) {
				if (b[h] != a[0][(z+op2)%n]) {//(z+op2)%n计算操作后的下标位置
					op2++;
					h = 0;
					z = 0;
					flag = 0;
					num = 0;
					continue;
				}//如果某一项不匹配,对第一行操作,并且对h,z重置
				else {
					h++;
					z++;
					num++;
				}//如果匹配就比对下一个数
				if (num == n-1 ) {
					flag = 1;
					break;
				}//如果n轮都顺利进行那就flag=1,退出
			}
		}
		if (flag == 1) {
			cout << op + op2;
			break;
		}//如果flag=1 输出答案
		else {
			int t = a[1][0];
			for (i = 0; i < n - 1; i++) {
				a[1][i] = a[1][i + 1];
			}
			op++;
			a[1][n - 1] = t;
		}//否则对二再进行操作
	}
	if (flag == 0) cout << "-1";//如果n轮下来都不匹配,就输出-1
	return 0;
}

​

  • 4
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值