Codeforces 4D题目链接
题目大意
有
1
1
1 封信和
n
n
n 封信封。信和信封都有宽度
w
w
w 和高度
h
h
h ,信装到信封里,信封再装到另一个信封里,最后求一个信封序列
A
=
{
a
1
,
a
2
,
.
.
.
,
a
n
}
A=\{a_1,a_2,...,a_n\}
A = { a 1 , a 2 , . . . , a n } ,表示第
i
i
i 封信的宽度和高度都严格大于第
i
−
1
i-1
i − 1 封。求使得这个序列最长的方案。
输入
n
n
n (信封数量),
w
,
h
w,h
w , h 为信的宽度和高度
(
1
≤
n
≤
5000
,
1
≤
w
,
h
≤
1
0
6
)
(1 ≤ n ≤ 5000, 1 ≤ w, h ≤ 10^6)
( 1 ≤ n ≤ 5 0 0 0 , 1 ≤ w , h ≤ 1 0 6 ) n行
w
i
,
h
i
w_i,hi
w i , h i 表示第
i
i
i 封信的宽度和高度
(
1
≤
w
i
,
h
i
≤
1
0
6
)
(1 ≤ w_i, h_i ≤ 10^6)
( 1 ≤ w i , h i ≤ 1 0 6 )
输出
序列的长度 序列内容(
i
d
id
i d 即为输入顺序)
思路
贪心 :将信封按照宽度(首选排序项)和高度排序,然后按次序选择。问题:可能存在有一封信封,宽度很小但高度很高使得后续的信封都不能装,这时候就应该放弃这封信封选择宽度大一点但是高度相对小一点的。
动态规划:
考虑
d
p
dp
d p ,设
d
p
[
i
]
dp[i]
d p [ i ] 为从
1
1
1 到
i
i
i 此时
i
i
i 能取得的最好的情况 考虑这个最好的情况需要存放哪些值
struct Node
{
int w;
int h;
int num;
int pre;
int id;
} ;
如何遍历:每次遍历到
i
i
i 时考虑比它小的坐标
1
−
j
1-j
1 − j 。判断是否能在
j
j
j 后面再加一个
i
i
i 。这样遍历去取得最大值。 注意排序必不可少。因为同样序列可能顺序不同导致结果不同,所以一定保证
w
w
w 或者
h
h
h 小的在前面。可以等价为,因为宽度已经排好序,就是求高度的最长上升子序列 。
代码
#include <cstdio>
#include <algorithm>
#include <string>
#include <cstring>
#include <iostream>
#include <cmath>
#include <vector>
#include <map>
using namespace std;
const int maxn = 5000 + 15 ;
struct Node
{
int w;
int h;
int num;
int pre;
int id;
} ;
Node dp[ maxn] , a[ maxn] ;
bool cmp ( const Node& A, const Node& B)
{
if ( A. w != B. w)
return A. w < B. w;
else
return A. h < B. h;
}
int main ( )
{
int n, width, height;
cin >> n >> width >> height;
memset ( dp, 0 , sizeof ( dp) ) ;
int w, h;
for ( int i = 1 ; i <= n; i++ )
{
cin >> a[ i] . w >> a[ i] . h;
a[ i] . id = i;
}
sort ( a + 1 , a + n + 1 , cmp) ;
for ( int i = 1 ; i <= n; i++ )
{
if ( a[ i] . w <= width || a[ i] . h <= height)
continue ;
else
{
dp[ i] . w = a[ i] . w;
dp[ i] . h = a[ i] . h;
dp[ i] . num = 1 ;
dp[ i] . pre = 0 ;
dp[ i] . id = a[ i] . id;
}
for ( int j = 1 ; j < i; j++ )
{
if ( dp[ j] . num > 0 && a[ i] . w > dp[ j] . w && a[ i] . h > dp[ j] . h && dp[ j] . num + 1 > dp[ i] . num)
{
dp[ i] . pre = j;
dp[ i] . num = dp[ j] . num + 1 ;
dp[ i] . w = a[ i] . w;
dp[ i] . h = a[ i] . h;
dp[ i] . id = a[ i] . id;
}
}
}
int Max = 0 ;
int id = 0 ;
for ( int i = 1 ; i <= n; i++ )
{
if ( dp[ i] . num > Max)
{
id = i;
Max = dp[ i] . num;
}
}
vector< int > ans;
for ( int i = id; i != 0 ; i = dp[ i] . pre)
ans. push_back ( dp[ i] . id) ;
cout << Max << endl;
for ( int i = ans. size ( ) - 1 ; i >= 0 ; i-- )
cout << ans[ i] << " " ;
cout << endl;
return 0 ;
}
好难受啊,最近在codeblocks和预览时的格式明明没有问题,为什么显示的时候就格式一团糟啊……