python搭积木_搭积木

12

/*

对长方形的宽w排序,本题化简为对长l求最长上升子序列。

本题只需求最长上升子序列的 长度,可优化到O(nlogn)

*/

#include

using namespace std;

#define N 1000000

struct rectangle {

int w = 0, l = 0;

} a[N];

int dp[N];

bool cmp(rectangle x, rectangle y){

return x.w == y.w ? x.l < y.l : x.w < y.w;

}

int main()

{

//    freopen("input.txt", "r", stdin);

int n;

cin >> n;

for(int i = 0; i < n; i++) {

cin >> a[i].w >> a[i].l;

}

sort(a, a + n, cmp);

dp[0] = a[0].l;

int len = 1;

for(int i = 1; i < n; i++) {

if(a[i].l >= dp[len-1]) {

dp[len++] = a[i].l;

} else {

*(upper_bound(dp, dp + len, a[i].l)) = a[i].l;

}

}

cout << len << endl;

return 0;

}

编辑于 2019-07-05 12:12:17

回复(5)

6

import java.io.BufferedReader;

import java.io.IOException;

import java.io.InputStreamReader;

import java.util.Arrays;

import java.util.TreeSet;

public class Solution3_搭积木 {

public static void main(String[] args) throws IOException {

BufferedReader bf = new BufferedReader(new InputStreamReader(System.in));

int n = Integer.parseInt(bf.readLine());

//保存积木的宽高的二维数组

int[][] bricks = new int[n][2];

String[] strs;

for (int i = 0; i < n; i++) {

strs = bf.readLine().split(" ");

bricks[i][0] = Integer.parseInt(strs[0]);

bricks[i][1] = Integer.parseInt(strs[1]);

}

if (n==1){

System.out.println(1);

return;

}

//按照宽进行排序,然后求长度的最长上升子序列

Arrays.sort(bricks, (a, b) -> a[0] - b[0]);

/**

* 我们按照宽度从小到大对 bricks 进行了排序

* dp数组中存储的数积木的长度,它是一个上升的数组,这样才能保证积木的层叠

*/

int[] dp = new int[n];

int count = 0;//层数

for (int i = 0; i < n; i++) {

if (count == 0 || bricks[i][1] >= dp[count - 1]) {

//当当前积木的长度 >= dp数组中保存的最大积木长度,那我们就将它加入到 dp 数组中,并且层数加一

dp[count] = bricks[i][1];

count++;

}else {

/**

* 这里解释一下:当我们加入的积木 bricks[i][1],它的长度小于dp中的最大长度

* 我们需要在数组dp中找到 <= bricks[i][1] 最接近的值的索引 index,将它替换成现在的长度 bricks[i][1]

* 为什么要替换: dp数组中积木的宽度都是小于 bricks[i]的,积木bricks[i]的宽度比dp[index]宽度大,

* 而且bricks[i]的长度 >= dp[index],在堆积木情况下,当然是优先选择宽度和长度更大的积木。

*/

int index = lowerBound(dp, 0, count, bricks[i][1]);

dp[index] = bricks[i][1];

}

}

System.out.println(count);

}

/**

* C++中存在的两个方法,用java实现一下

* ower_bound算法要求在已经按照非递减顺序排序的数组中找到第一个大于等于给定值key的那个数的索引,

* 其基本实现原理是二分查找

*/

public static int lowerBound(int[] nums,int l,int r,int target){

while(l

int m = (l+r)/2;

if(nums[m]>=target) r= m;

else l = m +1;

}

return l;

}

/**

* upper_bound函数要求在按照非递减顺序排好序的数组中找到第一个大于给定值key的那个数索引,

* 其基本实现原理是二分查找

*/

public static int upperBound(int []nums ,int l,int r, int target){

while(l

int m = (l+r)/2;

if(nums[m]<=target) l = m+1;

else r = m;

}

return l;

}

}

发表于 2019-08-03 15:44:14

回复(6)

2

/*

哪位大佬帮看一下啊?小数据测试都没问题,当积木数量到了10000之后,就报错了。找了很久不知道哪里出问题了 Q^Q public class DaJiMu {

public static void main(String[] args) throws IOException { BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(System.in));

int num = Integer.parseInt(bufferedReader.readLine());

int[][] jimu = new int[num][2];

for (int i = 0; i < num; i++){

String[] temp = bufferedReader.readLine().split(" ");

jimu[i][0] = Integer.parseInt(temp[0]);

jimu[i][1] = Integer.parseInt(temp[1]);

}

Arrays.sort(jimu, new Comparator() { @Override public int compare(int[] o1, int[] o2) {

return o1[0] != o2[0]? o1[0] - o2[0] : o1[1] - o2[1];

}

});

if( num == 1){

System.out.print(1);

return;

}

int max = 0;

int[] len = new int[num];

len[0] = 1;

//求最长递归子序列

for (int i = 1; i < num; i++){

int lastADDIndex = binarySearch(jimu, jimu[i][1], 0, i - 1);

//若非递减,则选择max(len[i-1]+1, len[差值最小]+1)较大的长度。

if (jimu[i][1] >= jimu[i-1][1])

if(lastADDIndex != -1)

len[i] = Math.max(len[i-1] + 1, len[lastADDIndex] + 1);

else

len[i] = len[i-1] + 1;

else{

if(lastADDIndex != -1){

len[i] = len[lastADDIndex] + 1;

}else

len[i] = 1;

}

if( max < len[i])

max = len[i];

}

System.out.print(max);

}

public static int binarySearch(int[][] arr, int key, int start, int end){ int max = -1;

int min = 1000000000;

while(start <= end){

int mid = start + (end - start) / 2;

if(arr[mid][1] <= key) { </

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值