我的编程之算法篇

本文介绍了两道洛谷平台上的编程竞赛题目,分别是NOIP2008提高组的‘传纸条’问题和NOIP1998普及组的‘三连击’挑战。对于‘传纸条’,博主通过动态规划和三维数组优化解决了纸条来回传递的最大路径问题;在‘三连击’中,博主展示了如何寻找满足特定条件的三位数组合。这两个问题都涉及到了数值处理和条件判断,解析了如何利用数学和逻辑思维解决编程竞赛中的实际问题。
摘要由CSDN通过智能技术生成

1.洛谷P1006 [NOIP2008 提高组] 传纸条

        P1006 [NOIP2008 提高组] 传纸条 - 洛谷 | 计算机科学教育新生态 (luogu.com.cn)

       思路分析:

        该题为经典的dp动态,除了起始点(1,1)和终点(n,m)纸条的来回传递位置不能重复,我们可以把该来回的过程看作是两个纸条从起始点到终点的过程。可以设置一个四位数组(F[r1][c2][r2][c2])来纪录两个点的位置。但是这样需要用四个循环,非常的费时间,可能会超时。所以我们改为三维数组(F[p][r1][r2])来记录,因为每时每刻两个纸条走的步数p相同。i, j分别表示他们处在的行数则他们的坐标分别为(i,p-i+1)   (j,p-j+1)。当i和j相等时即两点在同一位置(证明该点的值对上一步的两个纸条来说都比较大(如图))则点的值只能加一次。

 代码:

#include<cstring>
#include<algorithm>
#include<iostream>
using namespace std;

int f[110][60][60];
int a[60][60];

int main()
{
    int n, m;
    cin >> n >> m;
    for (int i = 1; i <= n; i++)
        for (int j = 1; j <= m; j++)
            cin >> a[i][j];
    f[1][1][1] = a[1][1];
    for (int p = 2; p <= n + m - 1; p++)
        for (int i = 1; i <= n && i <= p; i++)
            for (int j = 1; j <= n && j <= p; j++)
            {
                if (i == 1 && j == 1) continue;
                //找出上一步中的最大值
                f[p][i][j] = max(max(f[p - 1][i][j], f[p - 1][i - 1][j]), max(f[p - 1][i][j - 1], f[p - 1][i - 1][j - 1]));
                // 三目运算符  判断条件?true输出表达式1:false输出表达式2;然后求和
                //表达式1即为i和j相等,位置重复则只加一次
                f[p][i][j] += i == j ? a[i][p - i + 1] : a[i][p - i + 1] + a[j][p - j + 1];
            }
    printf("%d\n", f[n + m - 1][n][n]);
    return 0;
}

小知识点总结:

        三目运算符   判断条件?(true)输出表达式1:(false)输出表达式2;

2.洛谷 P1008 [NOIP1998 普及组]  三连击

P1008 [NOIP1998 普及组] 三连击 - 洛谷 | 计算机科学教育新生态 (luogu.com.cn)

        题目分析:

        将1到9组成三个三位数并且是1比2比3的关系,怎么组怎么比毫无头绪,但是组成的这三个数(假设能重复)各自的范围是100~333:334~666:667~999;不重复则最小的三位数是123,最大的为987,于是我们就有一个大胆的想法,让三个数分别为a,b,c。则可以让a从123开始循环b=2*a;c=3*a;保证abc三个数只能用一次1~9则将百位十位个位分离验证。

        知识点:

        分离百十个位方法  设该数为n

        百位=n%100;

        十位=n/10%10;

        个位=n%10;

        代码:

#include<iostream>
using namespace std;
int main()
{
	for (int a=123; a <= 333; a++)
	{
		int b, c;
		b = a * 2;
		c = a * 3;
		if ((a / 100 + a / 10 % 10 + a % 10 + b / 100 + b / 10 % 10 + b % 10 + c / 100 + c / 10 % 10 + c % 10 == 1+2+3+4+5+6+7+8+9)&&(   (a/100)*(a/10%10)*(a%10)*(b/100)*(b/10%10)*(b%10)*(c/100)*(c/10%10)*(c%10)==1*2*3*4*5*6*7*8*9  )  )
			cout << a <<"  " << b << "  " << c << endl;
		
	}
	return 0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值