HDU1677 Nested Dolls
2013-03-19 19:38
141 查看
/*
这是杭电1677那道题
这算一道动态规划题,说起动态规划,不得不说背包九讲真是大牛呀,每次看都会有些收获
这道题难点之一是将其转化为,求最长单调非递增子序列
记得刚开始看到这道题的时候,没头没脑就开始了贪心,直接超时,稍微修改下
wrong Anser
不得不另辟蹊径
我想起以前看过的一道题,
说是河流两岸有许多村庄 ,南岸一些村庄与北岸(南北村庄个数相同
,且只有唯一朋友)的一些村庄是朋友,可以开通航线
但政府为了安全起见,不允许航线出现交叉
咱们假设南岸用Cn表示北岸用Dn表示
C1 C2 C3 C4………………
D1 D1 D3 D4………………
假设上述的都是Dn--》Cn为合法路线
Cn有序时,那么D1<D2<D3<D4<………………
假设上述不成立 即D2>D3
因为C2<C3
C2D2与C3D3一定会相交,那么与我们的假设相矛盾
所以D2<D3成立
那么这一题化为了就转化,将南岸的村庄排序后,求北岸村庄
最长单调递增子序列,nlogn能搞定
这一题与我们所说的这一题有许多些相似性
我们只需要将“长”按递增,“长”相等时,高递减
然后求,高的单调非递增子序列(也就是非严格单调递减子序列)
这个序列的长度就是所求的答案
可以这样想
L1 L2 L3 L4 L5 L6
H1 H2 H3 H4 H5 H6
当L单调递增时要它们能装在一起Hx<H(x+1)
那么当Hi>=H(i+1)它们一定不能装在一起
都现在我们只能说至少需要longth(序列长度)
到现在还不能武断说所求答案就是longth,
剩下的我还真没想到什么好的证明方法
我只能凭着感性思维,去判断
假设 这个序列为
m1 m2 m3 m4 m5 m6
m1前面的有比m1小,假如有比他大的,m1可以更新为比它大的值,
长度增加,与题意不符m1与m2之间的值也都比m2小,同理可推到mi
再者假设m1前有两个比m2大的(这两个数一定正序序),否则序列长度增加
那么装m1的时候一定,可以把大于m2的全部装完
同理,一直推到mi,
设子序列最后一个数为m,比m大的在m前面的都全部装完了,
m后面的数也可以按上面分析方法,解决掉
到这里就应该说第二个难点了,也不算什么难点,但就是再求
这个子序列时,我犯了大错,结果刷了屏都没写正确,最后我的脑子
就成了浆糊了,那叫个悲哀呀,
要处理这个子序列,就必须明确,这些L1>=L2
他们是可以相等的,想必第二个问题在一些人眼里不是问题
*/
/*在证明这个算法时,纰漏很多,等以后思路清晰了,大脑明白了,
再去不这些证明吧,当然更期待路过的大神给已指正,谢谢!!!^_^*/
这是杭电1677那道题
这算一道动态规划题,说起动态规划,不得不说背包九讲真是大牛呀,每次看都会有些收获
这道题难点之一是将其转化为,求最长单调非递增子序列
记得刚开始看到这道题的时候,没头没脑就开始了贪心,直接超时,稍微修改下
wrong Anser
不得不另辟蹊径
我想起以前看过的一道题,
说是河流两岸有许多村庄 ,南岸一些村庄与北岸(南北村庄个数相同
,且只有唯一朋友)的一些村庄是朋友,可以开通航线
但政府为了安全起见,不允许航线出现交叉
咱们假设南岸用Cn表示北岸用Dn表示
C1 C2 C3 C4………………
D1 D1 D3 D4………………
假设上述的都是Dn--》Cn为合法路线
Cn有序时,那么D1<D2<D3<D4<………………
假设上述不成立 即D2>D3
因为C2<C3
C2D2与C3D3一定会相交,那么与我们的假设相矛盾
所以D2<D3成立
那么这一题化为了就转化,将南岸的村庄排序后,求北岸村庄
最长单调递增子序列,nlogn能搞定
这一题与我们所说的这一题有许多些相似性
我们只需要将“长”按递增,“长”相等时,高递减
然后求,高的单调非递增子序列(也就是非严格单调递减子序列)
这个序列的长度就是所求的答案
可以这样想
L1 L2 L3 L4 L5 L6
H1 H2 H3 H4 H5 H6
当L单调递增时要它们能装在一起Hx<H(x+1)
那么当Hi>=H(i+1)它们一定不能装在一起
都现在我们只能说至少需要longth(序列长度)
到现在还不能武断说所求答案就是longth,
剩下的我还真没想到什么好的证明方法
我只能凭着感性思维,去判断
假设 这个序列为
m1 m2 m3 m4 m5 m6
m1前面的有比m1小,假如有比他大的,m1可以更新为比它大的值,
长度增加,与题意不符m1与m2之间的值也都比m2小,同理可推到mi
再者假设m1前有两个比m2大的(这两个数一定正序序),否则序列长度增加
那么装m1的时候一定,可以把大于m2的全部装完
同理,一直推到mi,
设子序列最后一个数为m,比m大的在m前面的都全部装完了,
m后面的数也可以按上面分析方法,解决掉
到这里就应该说第二个难点了,也不算什么难点,但就是再求
这个子序列时,我犯了大错,结果刷了屏都没写正确,最后我的脑子
就成了浆糊了,那叫个悲哀呀,
要处理这个子序列,就必须明确,这些L1>=L2
他们是可以相等的,想必第二个问题在一些人眼里不是问题
*/
#include<stdio.h> #include<algorithm> using namespace std; #define N 30000 typedef struct { __int64 w,h; }Doll; bool comp(Doll a,Doll b) { if(a.w<b.w)return true; if(a.w==b.w&&a.h>b.h)return true; return false; } Doll doll ; __int64 num ; __int64 Midfind(__int64 x,__int64 low,__int64 high) { if(x>num[0])return 0; while(low<=high) { __int64 mid=(low+high)/2; if(num[mid]==x) return mid; else if(num[mid]>x) { low=mid+1; } else high=mid-1; } return high+1; } __int64 Count(__int64 n) { __int64 i,k,len; num[0]=doll[0].h; len=0; for(i=1;i<n;i++) { if(doll[i].h<=num[len]) { num[++len]=doll[i].h; } else { k=Midfind(doll[i].h,0,len); while(num[k]>=doll[i].h) k++; if(k>len)len=k; num[k]=doll[i].h; } } return len+1; } int main() { // freopen("Input.txt","r",stdin); __int64 t,i,n; scanf("%I64d",&t); while(t--) { __int64 w,h; scanf("%I64d",&n); for(i=0;i<n;i++) { scanf("%I64d%I64d",&w,&h); doll[i].w=w; doll[i].h=h; //doll[i].w=w<h?w:h; //doll[i].h=w>h?w:h; } sort(doll,doll+n,comp); printf("%I64d\n",Count(n) ); } }
/*在证明这个算法时,纰漏很多,等以后思路清晰了,大脑明白了,
再去不这些证明吧,当然更期待路过的大神给已指正,谢谢!!!^_^*/
相关文章推荐
- hdu1677 Nested Dolls(贪心)
- HDU1677:Nested Dolls
- hdu1257 最少拦截系统 hdu1677 Nested Dolls(最长上升子序列)
- hdu1677--Nested Dolls(贪心+LIS)
- hdu1677: Nested Dolls
- hdu 1677 Nested Dolls【贪心解嵌套娃娃问题】
- hdu----(1677)Nested Dolls(DP/LIS(二维))
- hdu 1677 Nested Dolls (Greedy + Treap)
- SPOJ 3943 - Nested Dolls 最长不下降子序列LIS(二分写法)
- EOJ1765 Nested Dolls 最长上升子序列
- poj3636 Nested Dolls
- AYITACM2016省赛第三周A-Nested Dolls(贪心解嵌套问题)
- HDU OJ 1677 Nested Dolls【二分,LIS】
- POJ 3636 俄罗斯Nested Dolls 贪心二分 动态规划
- SPOJ 3943 Nested Dolls
- 606第十周周六赛E - Nested Dolls 套玩具
- 3636 nested dolls{dilworth}
- HDOJ 1677 Nested Dolls(贪心+LIS)
- POJ3636Nested Dolls
- CSU 1892: Nested Dolls(2007 Nordic Collegiate Programming Contest)