本意是同时提供java以及c++两种语言的代码的题解
但是无奈oj网站一直欺负java语言慢, 因此本篇题解部分java代码只提供思路参考
不提供语言优化,有兴趣的同学可以自行优化java版本
过不了的java语言均已注明!
目录
4546. 最大和加强加强版 - 线性dp
java版 - 这个vjudge过不了 acw可以过
c++版
4547. 伊格内修斯和公主IV - 摩尔投票法
java版 - 超时tle 只提供思路
c++版
4548. 猴子和香蕉 - 二维最长上升子序列dp
4546. 最大和加强加强版 - AcWing题库
题目:
思路:
定义 f[i][j][k] :前 i 个数,构成 j 个组,且第 i 个数是否在第 j 个组(0/1表示是否存在)
属性:最大值max
状态划分:
(1)选择第i个数
- 第 i 个数在新开的组(前i-1个数已经构成j-1组)
- f[i][j][1] = max( f[i-1][j-1][0],f[i-1][j-1][0] )+ w[i]
- 第 i 个数在旧组(前i-1个数已经构成j组)
- f[i][j][1] = max( f[i][j][1],f[i-1][j][1]+w[i] )
(2)不选择第i个数
- f[i][j][0] = max( f[i-1][j][0],f[i-1][j][1] )
根据状态定义知答案为max(f[n][m][0],f[n][m][1])
因为i只与i-1层有关,所以可以进行优化&1
import java.util.*;
class Main
{
static int N=1000010,M=1010;
static long[][][] f=new long[2][M][2]; //f[i][j][k]前i个数,分成j组,第i个数是否在第j组(0/1表示)
static int[] w=new int[N];
public static void main(String[] args)
{
Scanner sc=new Scanner(System.in);
while(sc.hasNextLine())
{
String[] s=sc.nextLine().split(" ");
int m=Integer.parseInt(s[0]);
int n=Integer.parseInt(s[1]);
int cnt=2;
for(int i=1;i<=n;i++) w[i]=Integer.parseInt(s[cnt++]);
for(int i=0;i<2;i++)
for(int j=0;j
#include
#include
#include
#include
#include
4547. 伊格内修斯和公主IV - AcWing题库
题目:
思路:
摩尔投票法的经典应用
如果有一个数x出现次数超过一半,则通过1v1打擂台的方式
与和x不同的数两两抵消后仍然存在
原因是因为x超过一半,其他数和它同归于尽后,最后生存下来的绝对是x
import java.util.*;
class Main
{
public static void main(String[] args)
{
Scanner sc=new Scanner(System.in);
while(sc.hasNext())
{
int num=0,res=0;
int n=sc.nextInt();
while(n-->0)
{
int cur=sc.nextInt();
if(res==0) //第一个人当擂主
{
res=cur;
num=1;
}else if(cur!=res)
{
num--; //同归于尽
if(num==0) //如果擂主挂了 换新擂主
{
res=cur;
num=1;
}
}else num++;
}
System.out.println(res);
}
}
}
#include
#include
#include
#include
#include
4548. 猴子和香蕉 - AcWing题库
题目:
思路:
f[i]:前i个积木能堆起来的最大高度
先将每组数据的长宽高能摆放的所有情况存入数组
2种朝向×3种底面=6种摆放情况
按长宽从小到大排序,寻找满足 " 长和宽均递增 " 的最长上升子序列长度
不熟悉最长上升子序列dp模板的同学,可以学习一下:
【蓝桥杯集训26】线性DP(4 / 4)_Roye_ack的博客-CSDN博客
#include
#include
#include
#include
#include