HDU 1160 FatMouse‘s Speed

链接

FatMouse’s Speed - http://acm.hdu.edu.cn/showproblem.php?pid=1160

分析

  • LIS
  • 动态规划
  • 寻找“越胖越慢”证据,即寻找最长链
  • 速度降序,体重升序的最长链;
  • 每个长度的链保存一条,当链的最后一个重量变化时,复制前一个长度的链
  • 另一种思路:按序列的下标分类,即每个元素一类【注意:与每个元素的值分一类的区别】

代码

尾元素数组 +【路径二维数组】

/* hdu 1160 FatMouse's Speed */
#include 
using namespace std;
#define MXN 1010
int dp[MXN], t[MXN][MXN];
struct FM{
     
	int m, s, id;
}fm[MXN];
int main(){
     
	int cnt = 0, len, pm;
    while(scanf("%d %d", &fm[cnt+1].m, &fm[cnt+1].s) == 2){
     
		cnt++;
		fm[cnt].id = cnt;
	}
	sort(fm+1, fm+cnt+1, [](FM x, FM y){
      return x.s > y.s;});		
	memset(dp, 0, sizeof dp);
	memset(t, 0, sizeof t);
	len = 1, dp[1] = 1, t[1][1] = 1;
 	for(int i = 2; i <= cnt; ++i) {
     
		pm = lower_bound(dp+1, dp+len+1, i, [](int x, int y){
     
			return fm[x].m < fm[y].m;
		}) - dp;
		if(pm == len+1) len++;
		dp[pm] = i;		
		// 复制前一个链
		for(int j = 1; j < pm; ++j) t[pm][j] = t[pm-1][j];
		// 修改链的最后一个元素
		t[pm][pm] = i;
    }
	printf("%d\n", len);
	for(int i = 1; i <= len; ++i) printf("%d\n", fm[t[len][i]].id);
    return 0;
}

动态规划【一维前继数组】

/* hdu 1160 FatMouse's Speed */
#include 
using namespace std;
#define MXN 1010
int dp[MXN], pre[MXN];
struct FM{
     
	int m, s, id;
}fm[MXN];
int main(){
     
	int cnt = 0, len = 0, p;
    while(scanf("%d %d", &fm[cnt+1].m, &fm[cnt+1].s) == 2){
     
		cnt++;
		fm[cnt].id = cnt;
	}
	sort(fm+1, fm+cnt+1, [](FM x, FM y){
      return x.s > y.s;});
	memset(dp, 0, sizeof dp);
	memset(pre, 0, sizeof pre);
 	for(int i = 1; i <= cnt; ++i) {
     
		for(int j = 0; j < i; ++j){
     
			if(fm[i].m > fm[j].m && dp[i] < dp[j]+1){
     
				pre[i] = j;
				dp[i] = dp[j]+1;
			}
		}
    }
	for(int i= 1; i <= cnt; ++i) if(len < dp[i]) len = dp[i], p = i;
	printf("%d\n", len);
	cnt = len;
	while(p != 0){
     
		dp[cnt--] = fm[p].id;
		p = pre[p];
	}
	for(int i = 1; i <= len; ++i) printf("%d\n", dp[i]);
    return 0;
}

你可能感兴趣的:(算法入门,#,动态规划初步)