codeforces 4D D. Mysterious Present(dp)

题目连接:

codeforces 4D


题目大意:

给出n个信封,这n个信封有长和宽,给出卡片的尺寸,求取能够装入卡片的最长的序列,序列满足后一个的长和宽一定大于前一个,求最长的这个序列的长度,并且给出一组可行解。


题目分析:

  • 一看这种题目就是dp的题目,状态定义dp[i]为以i结尾的序列的最大的长度,并且利用一个数组记录得到最优解的路径,采取链表的形式进行存储。
  • 首先对给出的信封进行排序,按照宽为第一关键字,高为第二关键字,
  • 状态转移方程如下:

    dp[i]=maxj=0j?1{dp[j]+1},{a[j].w<a[i].w && a[j].h<a[i].h}
  • 答案递归地倒序输出即可。

AC代码:

#include <iostream>
#include <cstring>
#include <cstdio>
#include <algorithm>
#define MAX 5007

using namespace std;

int n,w,h;
int dp[MAX];
int back[MAX];

struct Node
{
    int w,h,x;
    bool operator < ( const Node & a ) const
    {
        if ( w == a.w ) return h < a.h;
        return w < a.w;
    }
}a[MAX];

void print ( int x )
{
    if ( a[x]. w <= w || a[x].h <= h ) return;
    print ( back[x] );
    printf ( "%d " , a[x].x );
}

int main ( )
{
    while ( ~scanf ( "%d%d%d" , &n , &w , &h ))
    {
        for ( int i = 1 ; i <= n ; i++ )
        {
            scanf ( "%d%d" , &a[i].w , &a[i].h );
            a[i].x = i;
        }
        dp[0] = -1;
        sort ( a+1 , a+n+1 );
        for ( int i = 1 ; i <= n ; i++ )
        {
            int temp = -1,id = 0;
            for ( int j = 0 ; j < i ; j++ )
                if ( a[j].w < a[i].w && a[j].h < a[i].h && a[j].w > w && a[j].h > h )
                    if ( temp < dp[j] )
                    {
                        temp = dp[j];
                        id = j;
                    }
            if ( a[i].w > w && a[i].h > h ) dp[i] = 1 , back[i] = 0;
            else dp[i] = -1;
            if ( temp+1 > dp[i] )
            {
                dp[i] = temp+1;
                back[i] = id;
            }
        }
        int maxn = 0;
        for ( int i = 1 ; i <= n ; i++ )
            maxn = max ( maxn , dp[i] );
        if ( maxn == 0 )
        {
            puts ( "0" );
            continue;
        }
        printf ( "%d\n" , maxn );
        for ( int i = 1 ; i <= n ; i++ )
            if ( maxn == dp[i] )
            {
                print ( i );
                puts ("");
                break;
            }
    }
}

版权声明:本文为博主原创文章,未经博主允许不得转载。

时间: 2024-11-06 07:16:04

codeforces 4D D. Mysterious Present(dp)的相关文章

codeforces4D - Mysterious Present DP

题意:求限定起始位置的二维最长递增子序列. 解题思路:直接DP 解题代码: 1 // File Name: 4d.cpp 2 // Author: darkdream 3 // Created Time: 2014年08月04日 星期一 19时24分49秒 4 5 #include<vector> 6 #include<list> 7 #include<map> 8 #include<set> 9 #include<deque> 10 #incl

HDU - 2145 zz&#39;s Mysterious Present (最短路)

题目大意:有一个人,办了一个party,先到的有礼物.如果有多个人同时到达,就去家离得最远的那个,如果还是多个人同时到达,就去那个编号最大的 解题思路:最短路水题... #include <cstdio> #include <cstring> #include <algorithm> #include <queue> #include <cmath> using namespace std; #define N 310 #define INF 0

Codeforces 360C Levko and Strings dp

题目链接:点击打开链接 题意: 给定长度为n的字符串s,常数k 显然s的子串一共有 n(n-1)/2 个 要求找到一个长度为n的字符串t,使得t对应位置的k个子串字典序>s #include<stdio.h> #include<iostream> #include<string.h> #include<algorithm> #include<vector> #include<set> using namespace std; #

CodeForces 30C Shooting Gallery 简单dp

题目链接:点击打开链接 给定n个气球 下面n行 x y t val 表示气球出现的坐标(x,y) 出现的时刻t,气球的价值val 枪每秒移动1个单位的距离 问: 射击的最大价值,开始时枪瞄准的位置任意. 思路: dp一下.. #include <cstdio> #include <cstring> #include <iostream> #include <algorithm> #include <math.h> #include <set

Codeforces 459E Pashmak and Graph(dp+贪心)

题目链接:Codeforces 459E Pashmak and Graph 题目大意:给定一张有向图,每条边有它的权值,要求选定一条路线,保证所经过的边权值严格递增,输出最长路径. 解题思路:将边按照权值排序,每次将相同权值的边同时加入,维护每个点作为终止点的最大长度即可. #include <cstdio> #include <cstring> #include <algorithm> using namespace std; const int maxn = 3

codeforces 149D - Coloring Brackets (区间dp)

题目大意: 给出一组合法的括号. 括号要么不涂颜色,要么就涂上红色或者绿色. 匹配的括号只能有一个有颜色. 两个相邻的括号不能有相同的颜色. 思路分析: 因为是一个合法的括号序列. 所以每个括号与之匹配的位置是一定的. 那么就可以将这个序列分成两个区间. (L - match[L] )  (match[L]+1, R) 用递归先处理小区间,再转移大区间. 因为条件的限制,所以记录区间的同时,还要记录区间端点的颜色. 然后就是一个递归的过程. #include <cstdio> #include

CodeForces 55D Beautiful numbers 数位DP+数学

题意大概是,判断一个正整数区间内有多少个整数能被它自身的每一个非零的数字整除. 因为每一个位置上的整数集s = {0,1,2,3,4,5,6,7,8,9} lcm(s) = 2520 现在有一个整数t是由s中一个或者多个数字构成的,记为abcde,显然t = a*10^4+b*10^3+c*10^2+d*10^1+e 要使得t能被a,b,c,d,e整除,必然有t % lcm(a,b,c,d,e) = 0 因为a,b,c,d,e去重之后一定是s的一个子集,所以lcm(s)一定是lcm(a,b,c,

Codeforces Round #626 D. Present 异或按位确定 +二分or双指针

Codeforces Round #626 D. Present 异或按位确定 +二分or双指针 题意 给n个数,求他们两两的和的异或结果 n(4e5) 值域(1e7) 思路 异或问题一般都是按位确定,那么怎么确定第k位的值呢.首先第k位的值只和[1,k]位有关系,也就是说只跟a[i]本来在这一位有的数和进位有关系.那么怎么处理和的问题呢.首先我们只考虑[1..k]位,那么他们的和记为sum,如果sum在第k位有值 那么sum的值为 \(2^k+x\)因为只考虑[1..k]位所以a的最大值为\(

Codeforces Beta Round #4 (Div. 2 Only) D. Mysterious Present

最长上升子序列,这种水题还是一眼就能看出来的. 题目大意: 主人公想在一张w*h的明信片外套信封.他有n个信封,每个信封的长宽给出,问最多能套多少层.给出从小到大的顺序. 解题思路: 最长上升子序列,只不过是记忆路径. 下面是代码: #include <set> #include <map> #include <queue> #include <math.h> #include <vector> #include <string> #