hdu 4293 的加强版, 区间dp
#include<iostream>
#include<cstdio>
#include<vector>
#include<algorithm>
#include<cstring>
using namespace std;
#define M 1210
struct Node
{
int x, y;
int n;
vector<int> v; // 记录区间内有哪些Turtles;
void init(){
n = 0;
v.clear();
}
bool operator < (const Node a ) const
{
return y < a.y;
}
}node[M];
int vis[M][M], n;
int mark[M];
int dp[M], p[M];
vector<int>g[M];
void init()
{
for(int i = 0; i <= n; i++){
node[i].init();
g[i].clear();
}
memset(vis, -1, sizeof(vis));
memset(dp, 0, sizeof(dp));
memset(p, -1, sizeof(p));
memset(mark, 0, sizeof(mark));
}
int main()
{
int a, b, e;
while( scanf( "%d", &n ) == 1 ){
init();
e = 0;
for(int i = 1; i <= n; i++){
scanf( "%d%d", &a, &b);
if( a + b >= n ) //前后乌龟加起来大于等于n是不可能的;
continue;
if( vis[a+1][n-b] == -1 ){ //记录[a+1, n-b]的区间的标号
node[e].x = a+1; node[e].y = n-b;
node[e].n = 1;
node[e].v.push_back( i );
vis[a+1][n-b] = e++;
}
else{
int id = vis[a+1][n-b];
if( node[id].n < n-b-a ){ //区间最多容纳n-a-b个乌龟;
node[id].v.push_back(i);
node[id].n++;
}
}
}
if( e == 0 ){
printf( "%d", n );
for( int i = 1; i <= n; i++ )
printf( " %d", i );
printf( "\n" );
continue;
}
sort( node, node + e );
int cnt = 0;
int j = 0;
for( int i = node[0].y; i <= node[e-1].y; i++ ){ //DP
dp[i] = dp[i-1]; p[i] = p[i-1];
while( j < e && node[j].y == i ){
int xx = node[j].x - 1; //当前区间的前一坐标
if( dp[i] < dp[xx] + node[j].n ){
dp[i] = dp[xx] + node[j].n;
if( p[xx] == -1 ){
g[cnt].push_back( j );
p[i] = cnt++; //g[cnt]是存不连续的区间, p[i]是vector的下标;
}
else{
int id = p[xx];
for( int k = 0; k < g[id].size(); k++ )
g[cnt].push_back( g[id][k] );
g[cnt].push_back( j ); //加上当前区间
p[i] = cnt++;
}
}
j++;
}
}
printf( "%d", n - dp[node[e-1].y] );
int id = p[node[e-1].y];
for(int i = 0; i < g[id].size(); i++){
int ii =g[id][i];
for( int j = 0; j < node[ii].n; j++ )
mark[node[ii].v[j]] = 1;
}
for( int i = 1; i <= n; i++ ){
if( !mark[i] )
printf(" %d", i );
}
printf( "\n" );
}
}