薯队长写了n篇笔记,编号从1~n,每篇笔记都获得了不少点赞数。
薯队长想从中选出一些笔记,作一个精选集合。挑选的时候有两个规则:
1.不能出现连续编号的笔记。
2.总点赞总数最多
如果满足1,2条件有多种方案,挑选笔记总数最少的那种
输入包含两行。第一行整数n表示多少篇笔记。 第二行n个整数分别表示n篇笔记的获得的点赞数。(0<n<=1000, 0<=点赞数<=1000)
输出两个整数x,y。空格分割。x表示总点赞数,y表示挑选的笔记总数。
4 1 2 3 1
4 2
import java.util.Scanner;
public class Main{
public static void main(String[] args){
Scanner sc=new Scanner(System.in);
int n=sc.nextInt();
int[] f=new int[n+1];//总点赞数
int[] count=new int[n+1];//挑选笔记数
int[] up=new int[n+1];//每一篇的点赞数
for(int i=1;i<=n;i++){
up[i]=sc.nextInt();
}
count[1]=1;
f[1]=up[1];
for(int i=2;i<=n;i++){
f[n]=Math.max(f[n-2]+up[n],f[n-1]);
if(f[n]==f[n-1]){
count[n]=count[n-1];
}else{
count[n]=count[n-2]+1;
}
}
System.out.println( f[n]+" "+count[n]);
}
}
//我这个有什么问题啊,我找不到,通过不了,呜呜呜 #include <iostream>
#include <vector>
using namespace std;
int buffer[10001];
int main()
{
int n;
cin >> n;
for(int i=0; i<n; ++i) cin >> buffer[i];
vector<pair<int, int>> dp(n);
for(int i=0; i<n; ++i){
if(i == 0) dp[i].first = buffer[i], dp[i].second = 1;
else{
auto cur = buffer[i] + (i-2 >= 0 ? dp[i-2].first : 0);
auto cnt = i-2 >= 0? dp[i-2].second +1 : 1;
if(cur > dp[i-1].first) dp[i] = {cur, cnt};
else dp[i] = dp[i-1];
}
}
cout << dp.back().first << ' ' << dp.back().second;
return 0;
} 本题是动态规划问题,设 dp[i] 为前 i 个物品的最大挑选赞数, 状态转移方程是dp[i]=max(dp[i-1], dp[i-2]+nums[i])
#include<bits/stdc++.h>
using namespace std;
#define MAX_N 1010
int N;
int nums[MAX_N];
int main() {
scanf("%d", &N);
for (int i = 0; i < N; ++i) {
scanf("%d", &nums[i]);
}
int dp_0 = 0;
int dp_1 = 0;
int num_0 = 0, num_1 = 0;
for (int i = 0; i < N; ++i) {
int temp = dp_1;
int num_temp = num_1;
if (dp_1 < dp_0+nums[i]) {
dp_1 = dp_0+nums[i];
num_1 = num_0+1;
}
dp_0 = temp;
num_0 = num_temp;
}
printf("%d %d\n", dp_1, num_1);
return 0;
}
import sys n = eval(input()) nums = [int(i) for i in sys.stdin.readline().split()] dp = [0 for _ in range(n+2)] dpNum = [0 for _ in range(n+2)] num = 0 for i in range(n-1, -1, -1): if dp[i+1] < dp[i+2]+nums[i]: dp[i] = dp[i+2]+nums[i] dpNum[i] = dpNum[i+2]+1 else: dp[i] = dp[i+1] dpNum[i] = dpNum[i+1] print(dp[0], dpNum[0])
#include <iostream>
#include <vector>
using namespace std;
// dp[i]: 从第一篇笔记开始选到第i篇, 所能得到的最大点赞数。
// count[i]: 此时选取的笔记数量
int main(){
int n, val;
cin >> n;
vector<int> vec(n + 1, 0);
for(int i = 1; i <= n; ++i){
cin >> val;
vec[i] = val;
}
vector<int> dp(n + 1, 0);
vector<int> count(n + 1, 0);
dp[1] = vec[1]; //选第一篇笔记, 最大点赞数自然就是vec[1]
count[1] = 1; //选了一个数
for(int i = 2; i <= n; ++i){
//选了dp[i - 2], 就不能选dp[i - 1], 但可以选vec[i](不能连续)
if(dp[i - 1] < dp[i - 2] + vec[i]){
dp[i] = dp[i - 2] + vec[i];
count[i] = count[i - 2] + 1;
} else{
//不选dp[i - 2]和vec[i]
dp[i] = dp[i - 1];
count[i] = count[i - 1];
}
}
cout << dp[n] << ' ' << count[n] << endl;
return 0;
} 最后,leetcode 337题 打家劫舍III,思路类似,只不过从数组变成二叉树,感兴趣的可以试试。https://leetcode-cn.com/problems/house-robber-iii/def getMaxStar(n,nums): dp = [0 for _ in range(n+1)] dp2 = [0 for _ in range(n+1)] dp[1] = nums[0] dp2[1] = 1 for i in range(2,n+1): if dp[i-1] < dp[i-2]+nums[i-1]: dp[i] = dp[i-2]+nums[i-1] dp2[i] = dp2[i-2]+1 else: dp[i] = dp[i-1] dp2[i] = dp2[i-1] print(dp[-1], dp2[-1]) n = eval(input()) nums = [int(i) for i in input().split()] getMaxStar(n, nums)
var a = readline();
var c = readline();
c = c.split(" ");
var b = c.map(item =>{
return Number(item)
})
var point = [];
var num = [];
point[0] = b[0];
num[0] = 1;
point[1] = Math.max(b[0],b[1]);
num[1] = 1;
for (var i = 2; i < b.length; i++) {
if(b[i] + point[i - 2] > point[i - 1]){
point[i] = b[i] + point[i - 2];
num[i] = 1 + num[i-2];
} else {
point[i] = point[i - 1];
num[i] = Math.min(num[i - 1] , 1 + num[i - 2])
}
}
var res = [];
res.push(Math.max(...point));
let record = point.indexOf(res[0]);
res.push(num[record])
console.log(res[0] , res[1]) import java.util.*;
public class Main{
public static void main(String[] args){
Scanner sc=new Scanner(System.in);
int n=Integer.parseInt(sc.nextLine());
int[] num=new int[n];
for(int i=0;i<n;i++){
num[i]=sc.nextInt();
}
int[] dp=new int[n+1];
if(num.length==1){
System.out.println(num[0]+" "+1);
}
if(num.length==2){
System.out.println((num[0]>num[1]?num[0]:num[1])+" "+1);
}
dp[0]=num[0];
dp[1]=num[0]>num[1]?num[0]:num[1];
int[] dpN=new int[n];
dpN[0]=1;
dpN[1]=1;
for(int i=2;i<n;i++){
if(dp[i-1]<dp[i-2]+num[i]){
dp[i]=dp[i-2]+num[i];
dpN[i]=dpN[i-2]+1;
}else{
dp[i]=dp[i-1];
dpN[i]=dpN[i-1];
}
}
System.out.println(dp[n-1]+" "+dpN[n-1]);
}
} import java.util.*;
public class Main{
public static void main(String[] args){
Scanner in = new Scanner(System.in);
int n = in.nextInt();
int[] counts = new int[n];
for(int i = 0; i < n; i++){
counts[i] = in.nextInt();
}
//从右向左看,第i个开始的点赞数
//选取n+1作为容量且从1开始的原因是判断时需要n-2选项。dp[0]=0
int[] dp = new int[n+1];
dp[1] = counts[0];
int[] cp = new int[n+1];
//不赋值,初始值默认为0,不符合实际。
cp[1] =1;
for(int i=2;i<n+1;i++){
//选取自己作为第一个与选取后一个比那一个更大
if(dp[i-2]+counts[i-1]>dp[i-1]){
dp[i] = dp[i-2]+counts[i-1];
cp[i] = cp[i-2]+1;
}else{
dp[i] = dp[i-1];
cp[i] = cp[i-1];
}
}
System.out.println(dp[n]+" "+cp[n]);
}
}
#include<bits/stdc++.h>
using namespace std;
int main()
{
int n;
while(cin>>n)
{
vector<int> v(n+1);
int num=0;
for(int i=1;i<=n;i++)
{
cin>>num;
v[i]=num;
}
int dp[n+1];
int dpNum[n+1];
memset(dpNum,0,sizeof dpNum);
memset(dp,0,sizeof dp);
dp[1]=v[1];dpNum[1]=1;
for(int i=2;i<=n;i++)
{
if(dp[i-2]+v[i]>dp[i-1])
{
dp[i]=dp[i-2]+v[i];
dpNum[i]=dpNum[i-2]+1;
}
else{
dp[i]=dp[i-1];
dpNum[i]=dpNum[i-1];
}
}
cout<<dp[n]<<" "<<dpNum[n]<<endl;
}
return 0;
} public class Main {
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
int n = sc.nextInt();
int[] nums = new int[n];
for(int i = 0; i < nums.length; i++) {
nums[i] = sc.nextInt();
}
int[] dp = new int[n+1]; // 总点赞数
dp[1] = nums[0];
int[] dpN = new int[n+1]; // 挑选笔记数
dpN[1] = 1;
for(int i = 2; i <= n; i++) {
if(dp[i-1] < dp[i-2] + nums[i-1]) { // 选
dp[i] = dp[i-2] + nums[i-1];
dpN[i] = dpN[i-2] + 1;
} else { // 不选
dp[i] = dp[i-1];
dpN[i] = dpN[i-1];
}
}
System.out.println(dp[n] + " " + dpN[n]);
}
} 这个问题可以通过动态规划来解决。我们定义两个数组dp和count,其中:
动态规划的状态转移方程如下:
初始化:
最终结果为dp[n-1]和count[n-1]。
def select_notes(n, likes): if n == 0: return 0, 0 if n == 1: return likes[0], 1 # 初始化dp和count数组 dp = [0] * n # 在前 i 篇笔记中能获得的最多点赞数 count = [0] * n # 在前 i 篇笔记中能获得 dp[i] 个点赞数所需要的最少笔记数 dp[0] = likes[0] count[0] = 1 dp[1] = max(likes[0], likes[1]) count[1] = 1 # 不能选连续的,只能二选一,选大的 for i in range(2, n): if dp[i - 1] >= dp[i - 2] + likes[i]: # 只是>不行,无法使笔记数最小 dp[i] = dp[i - 1] count[i] = count[i - 1] else: dp[i] = dp[i - 2] + likes[i] count[i] = count[i - 2] + 1 return dp[-1], count[-1] # 输入处理 n = int(input()) likes = list(map(int, input().split()))
const rl = require("readline").createInterface({ input: process.stdin });
var iter = rl[Symbol.asyncIterator]();
const readline = async () => (await iter.next()).value;
void async function () {
// Write your code here
while(line = await readline()){
let arr=line.split(' ')
let dp=[]
let g=[]
if(arr.length<2) continue
arr=arr.map((item)=>{
return Number(item)
})
dp[0]=arr[0]
dp[1]=arr[1]
g[0]=1
g[1]=1
for(let i=2;i<arr.length;i++){
dp[i]=Math.max(dp[i-1],dp[i-2]+arr[i])
if(dp[i]==dp[i-2]+arr[i]){
g[i]=g[i-2]+1
}else{
g[i]=g[i-1]
}
}
console.log(dp[arr.length-1]+" "+g[arr.length-1])
}
}()
为啥只通过了八组有没有大佬解读一下
import java.util.*;
public class Main
{
public static void main(String[] args)
{
Scanner scanner = new Scanner(System.in);
int n = scanner.nextInt();
int[] upvotes = new int[n];
for (int i = 0; i < n; i++)
upvotes[i] = scanner.nextInt();
int[][] dp = new int[n + 1][2];
dp[1][0] = upvotes[0];
dp[1][1] = 1;
for (int i = 2; i <= n; i++)
{
if (dp[i - 1][0] < dp[i - 2][0] + upvotes[i - 1])
{
dp[i][0] = dp[i - 2][0] + upvotes[i - 1];
dp[i][1] = dp[i - 2][1] + 1;
}
else if (dp[i - 1][0] > dp[i - 2][0] + upvotes[i - 1])
{
dp[i][0] = dp[i - 1][0];
dp[i][1] = dp[i - 1][1];
}
else
{
dp[i][0] = dp[i - 1][0];
dp[i][1] = Math.min(dp[i - 1][1], dp[i - 2][1] + 1);
}
}
System.out.println(dp[n][0] + " " + dp[n][1]);
}
} n = int(input()) line = [int(i) for i in input().split()] if n == 0: print(0, 0) elif n == 1: print(line[0], 1) else: # dp[i] 表示考虑到第 i 篇笔记时的最大点赞总数 dp = [0] * n # count[i] 表示达到 dp[i] 的点赞总数时所选笔记的最少数量 count = [0] * n dp[0] = line[0] count[0] = 1 dp[1] = max(line[0], line[1]) count[1] = 1 if line[0] > line[1] else 1 for i in range(2, n): if dp[i-2] + line[i] > dp[i-1]: dp[i] = dp[i-2] + line[i] count[i] = count[i-2] + 1 elif dp[i-2] + line[i] == dp[i-1]: dp[i] = dp[i-2] + line[i] count[i] = min(count[i-2] + 1, count[i-1]) else: dp[i] = dp[i-1] count[i] = count[i-1] print(dp[-1], count[-1])