UVA 10131 - Is Bigger Smarter

题目大意: 给出一些大象,包含它的重量、智商。要你找出最长的序列,满足重量越大、智商越低。(严格增减)

题目类型:dp / LIS

题目分析:

把大象按重量升序排序,然后在此序列中对智商属性找最长单减子序列。要注意的是,题目要求的都是严格增减,所以要在判断条件里考虑相等的情况以排除(主要是重量)。

另外还要注意,排序后,序就不是原来的序了,而题目要求输出原序。所以在排序时维护一个r[]数组。

对于 最长单减子序列 的dp,状态转移方程(2种):

//d[i] = max{d[j]+1 | s[i]>s[j]; j = (i, n);} //d[i] 表示以 i 开头的 最长 递减子序列
//d[i] = max{d[j]+1 | s[i]<s[j]; j = [0, i);} //d[i] 表示以 i 结尾的 最长 递减子序列

代码:

 #include<cstdio> #include<cstring> #include<algorithm> using namespace std; #define MAXN 1002 struct ele { int w, s; int next; int xh; }e[MAXN]; int r[MAXN]; //用于保留对应的原序 int n; int d[MAXN]; int vis[MAXN]; //d[i] = max{d[j]+1 | s[i]>s[j]; j = (i, n);} //d[i] 表示以 i 开头的 最长 递减子序列 //d[i] = max{d[j]+1 | s[i]<s[j]; j = [0, i);} //d[i] 表示以 i 结尾的 最长 递减子序列 int dp(int cur) //以cur,做开头 { if(vis[cur]) return d[cur]; vis[cur] = 1; int max = 1; for(int i=cur+1; i<n; i++) if(e[i].s<e[cur].s && e[i].w>e[cur].w) //找降序 //注意w 严格增 ② { int t = dp(i)+1; max = max>t? max: (e[cur].next = i, t); } return d[cur] = max; } void print(int x) { //d[x] = 1 说明 停止 while(1) { printf("%d/n", e[x].xh+1); //从1开始,④ /// debug // printf("w=%d, iq=%d/n", e[x].w, e[x].s); if(d[x]==1) break; x = e[x].next; } } int cmp(ele a, ele b) //sort 中 参数 完全可以不用是 const 用于改值,很好用! ③ { if(a.w<b.w) { return 1; } else { int t = a.xh; a.xh = b.xh; b.xh = t; return 0; } } int main() { n=0; for(int i=0; scanf("%d%d", &e[i].w, &e[i].s)!=EOF; i++, n++) { e[i].xh = i; } sort(e, e+n, cmp); //按 w 升序 memset(vis, 0, sizeof(vis)); int max = 1; int ans; for(int i=0; i<n; i++) { max = max > dp(i)? max: (ans = i, dp(i)); } printf("%d/n", max); print(ans); }

转载于:https://www.cnblogs.com/tclh123/archive/2011/05/13/2587097.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值