• 博客园logo
  • 会员
  • 周边
  • 新闻
  • 博问
  • 闪存
  • 众包
  • 赞助商
  • Chat2DB
    • 搜索
      所有博客
    • 搜索
      当前博客
  • 写随笔 我的博客 短消息 简洁模式
    用户头像
    我的博客 我的园子 账号设置 会员中心 简洁模式 ... 退出登录
    注册 登录
jacklee404
Never Stop!
博客园    首页    新随笔    联系   管理    订阅  订阅
青蛙过桥 DP + 字典序

青蛙过桥 DP + 字典序

题目

一座长度为n的桥,起点的一端坐标为0,且在整数坐标i处有a[i]个石头【0<=a[i]<=4】,
一只青蛙从坐标0处开始起跳,一步可以跳的距离为1或2或3【即每一步都会落在整数点处】,
青蛙落在i处会踩着该点的所有石头,求青蛙跳出这座桥最少踩多少个石头?并且输出依次跳
过的坐标点路线,如果存在多种路线,输出字典序最小的那一条。

输入格式:

第一行整数n(<150000),接着下一行会有n+1个由空格隔开的整数,即桥上各个坐标处石头数量。

输出格式:

第一行为踩着最少石头个数,第二行为依次跳过的坐标点【字典序最小的】。

输入样例:

在这里给出两组输入。例如:

10
1 2 1 3 0 3 1 2 1 1 2
100
1 2 0 4 0 1 3 4 2 2 1 3 1 4 0 3 0 1 2 3 3 2 2 0 1 0 0 0 0 1 2 1 3 4 0 3 4 4 1 0
4 1 3 1 1 2 3 4 4 4 0 2 0 1 1 1 3 1 3 2 1 2 4 1 2 1 4 1 0 0 1 2 3 0 2 4 4 0 0 4
2 0 0 2 1 3 3 3 0 0 2 0 0 1 2 4 2 2 2 4 0

输出样例:

在这里给出对应的输出。例如:

4
0 2 4 6 8
36
0 2 4 5 8 10 12 14 16 17 20 23 25 26 27 28 31 34 35 38 39 41 44 47 50 52 54 57 60 63 65 68 69 70 73 74 77 78 81 82 85 88 89 91 92 94 97 100

Code Size Limit

16 KB

Time Limit

1000 ms

Memory Limit

64 MB

思路

​ 一开始求的时候正序, 但是其实这样并不能保证字典序, 我们可以采取倒序的方法, 倒序 我们只需要保证优先走最大距离的步数,这样能够同时保证字典位数最小,并且字典序最小(数字最小), 所以直接reverse, 然后dp就行了, 这里有个小技巧,其实输出不用保存在reverse,直接递归先中控制一下即可。

Code

#include <bits/stdc++.h>
// #inclue
using i64 = long long;

const int N = 5e5;

int n, a[N], dp[N], cnt;

int pre[N];

std::vector<int> g[N];

void out(int s) {
	if (s == 0) {
		// std::cout << s;
		// g[cnt].push_back(s);
		return;
	}

	if (n - s + 1) {
		std::cout << " ";
	}

	std::cout << n - s + 1;

	out(pre[s]);
}

int main() {
	std::cin >> n;

	for (int i = 0; i <= n; i ++) {
		std::cin >> a[i];
	}

	std::reverse(a + 0, a + 2 + n);

// 	for (int i = 0; i <= n + 1; i ++) {
// 		std::cout << a[i] << " \n"[i == n + 1];
// 	}

	dp[0] = a[0];

	for (int i = 1; i <= n + 1; i ++) {
		dp[i] = dp[i - 1] + a[i];
		
		pre[i] = i - 1;

		if (i - 2 >= 0) {
			if (dp[i] > dp[i - 2] + a[i]) {
				pre[i] = i - 2;
			}
			dp[i] = std::min(dp[i], dp[i - 2] + a[i]);
		}
		
		if (i - 3 >= 0) {
			if (dp[i] > dp[i - 3] + a[i]) {
				pre[i] = i - 3;
			}
			dp[i] = std::min(dp[i], dp[i - 3] + a[i]);
		}

		
	}

	std::cout << dp[n + 1] << "\n";

	out(n + 1);
}
posted on 2023-04-03 11:24  Jack404  阅读(71)  评论(0)    收藏  举报
刷新页面返回顶部
博客园  ©  2004-2026
浙公网安备 33010602011771号 浙ICP备2021040463号-3