这道题相当的经典,本身就有很多做法,而CQF大牛的做法尤为精妙。
给出一系列零件Si,零件有两个参数Ai Bi。现在将其排序,要求若i>j,则Ai>=Aj Bi>=Bj。也就是前面的两个参数要分别小于等于后面的两个参数。求此队列的最大长度。
那么如果将其投影到二维平面上,对每个零件Ai Bi点计数,那么问题就转换成为从最左下的1 1到左上的100 100,只能向右和向上运动,求运动过程中的访问总和最大值。
因此只要把每个点下面和左面的点比较,大者记入此点总和即可。
今天偶然看了一下排名,ZOJ果然有没落的倾向,而据说POJ越来越繁荣了。
#include <cstdio>
#include <string>
int n, a[101][101], b[101][101], nx, ny, mx, my;
int maxi ( int a, int b )
{
return a > b ? a : b;
}
void pb ()
{
//printf ( "%d %d %d %d\n", mx, my, nx, ny );
int i, k;
for ( i = nx; i <= mx; i ++ )
{
for ( k = ny; k <= my; k ++ )
{
printf ( "%d ", b[i][k] );
}
printf ( "\n" );
}
}
void init ()
{
memset ( a, 0, sizeof (a) );
memset ( b, 0, sizeof (b) );
mx = my = 0, nx = ny = 101;
}
int dp ()
{
int i, k;
for ( i = nx; i <= mx; i ++ )
{
for ( k = ny; k <= my; k ++ )
{
b[i][k] = maxi ( b[i - 1][k], b[i][k - 1] );
if ( a[i][k] ) b[i][k] += a[i][k];
}
}
//pb ();
return b[mx][my];
}
int main ()
{
//freopen ( "in.txt", "r", stdin );
while ( scanf ( "%d", &n ) )
{
if ( !n )
{
printf ( "*\n" );
break;
}
int i, x, y;
init ();
for ( i = 0; i < n; i ++ )
{
scanf ( "%d %d", &x, &y );
a[x][y] ++;
if ( x > mx ) mx = x;
if ( y > my ) my = y;
if ( x < nx ) nx = x;
if ( y < ny ) ny = y;
}
printf ( "%d\n", dp () );
}
return 0;
}
2210940 | 2007-01-27 21:57:54 | Accepted | 1787 | C++ | 00:00.01 | 472K | Crux.D |
评论