uva 10154 贪心+dp
题目链接:https://uva.onlinejudge.org/index.php?option=com_onlinejudge&Itemid=8&page=show_problem&problem=1095
题目大意:有许多只王八,每一只王八有着两个属性,重量w和力量s,这些王八最多能叠多少层不会让出现王八被压死,注意王八承受的重量
要算上自己的重量
思路分析:首先是贪心,我们要选择力量最大的王八放在下面是最优的,证明如下
分析,如果力量大的在下面,力量小的在上面,那么力量大的还能承受的重力就是s[da]-w[xiao]-w[da],力量小的能够承受的重力为s[xiao],前者可能大于,等于,或小于后者;如果力量小的在下面,力量大的在上面,那么力量小的能够承受的重力就是s[xiao]-w[xiao]-w[da],力量大的能够承受的重力为s[da],前者一定小于后者,总的承重能力受制于前者。这两种方式 第二种的总的承重能力显然不及第一种,也就是第一种更优,所以力量大的在下面一定比力量轻的在下面更好。所以我们按力量排序。
按力量排序以后然后dp[i]代表叠i层所需要的最小的重量,按照01背包写法01滚动即可
代码:
#include <iostream> #include <cstdio> #include <algorithm> #include <cstring> #include <cmath> using namespace std; const int maxn=6000; struct node { int w; int s; }; node t[maxn]; int dp[maxn]; bool cmp(node a,node b) { if(a.s==b.s) return a.w<b.w; else return a.s<b.s; } const int inf=0xfffff; int main() { int a,b; int tot=1; while(scanf("%d%d",&a,&b)!=EOF) { if(b>=a) t[tot].w=a,t[tot++].s=b; // if(tot==5) break; } sort(t+1,t+tot,cmp); for(int i=1;i<tot;i++) { dp[i]=inf; } dp[0]=0; int ans=0; for(int i=1;i<tot;i++) { for(int j=tot-1;j>=1;j--) { if(t[i].s>dp[j-1]+t[i].w) { dp[j]=min(dp[j],dp[j-1]+t[i].w); if(dp[j]<inf) ans=max(ans,j); } } } printf("%d\n",ans); }