标签:位置 cout F12 sort for maximum 关联 clu main
HDU-1024:Max Sum Plus Plus
题意:给m和n和n个数,在n个数里面选取m个互不相交的子段,使他们加和最大,输出最大值,
解:1.在n个数里面选取m段,子问题就可以看成j个数里取i段,就会有状态(i,j),如果推i,dp[j][i]代表从前j个数里取i段,那这和dp[j][i+1]没有特别明显的关联;所以选择推j。
2.dp[i][j]代表在前j个数中选择i段,那么对于当前j,要么不取、要么和第i段合并、要么单独作为第i段和前i-1段加和。
3.对于第一种情况,不取的情况,这时的值已经保存在了dp[i][j-1]中,所以不用考虑,那么递推关系式就是dp[i][j]=max(dp[i[j-1],dp[i-1][k])+a[j](i-1<=k<=j-1),
4.得用滚动数组,将前面的i提出来,用pre保存上一轮前j-1个数的最大值,就改为了dp[j]=max(dp[j-1],pre[j-1])+a[j]
1 for(int i=1;i<=m;i++) 2 { 3 p=-inf; 4 for(int j=i;j<=n;j++) 5 { 6 dp[j]=max(dp[j-1],pre[j-1])+a[j]; 7 //更新dp[j]后才更新的pre[j-1],因此pre[j-1]中存储的是 8 //上一轮前j-1个数的i-1段的最大值 9 pre[j-1]=p; 10 p=max(p,dp[j]);//p来记录最大值 11 } 12 } 13 //注意最后输出的是p,因为a[n]可能不取,那答案就在前n个dp中
HDU-1069:Max Sum Plus Plus
题意:给n块石头的长宽高,每种无限块,垒起来的最高高度,下面的那一块的长宽高都必须绝对大于上面的长宽,
解:1.很容易想到dp[i],代表以第i块石头为底时的最高高度,
2.因为要绝对大于上面的那一块,所以每种存储三个,x<y,然后排序即可,最后要遍历一遍dp数组取最大值,总是惯性思维感觉最后一个位置的数就是最大的
#include<iostream> #include<cstring> #include<string> #include<algorithm> #include<stdio.h> using namespace std; struct l{ int x,y,z; }len[100]; int n; int ll[3]; int dp[100]; bool cmp(const l &a,const l &b) { if(a.x==b.x) return a.y<b.y; else return a.x<b.x; } int main() { int t=1; while(cin>>n&&n) { int cnt=0; for(int i=0;i<n;i++) { scanf("%d %d %d",&ll[0],&ll[1],&ll[2]); sort(ll,ll+3); len[cnt].x=ll[0],len[cnt].y=ll[1],len[cnt].z=ll[2];cnt++; len[cnt].x=ll[1],len[cnt].y=ll[2],len[cnt].z=ll[0];cnt++; len[cnt].x=ll[0],len[cnt].y=ll[2],len[cnt].z=ll[1];cnt++; } sort(len,len+cnt,cmp); for(int i=0;i<cnt;i++) { //cout<<len[i].x<<" "<<len[i].y<<" "<<len[i].z<<‘\n‘; dp[i]=len[i].z; } for(int i=0;i<cnt;i++) { for(int j=0;j<i;j++) { if(len[j].x<len[i].x&&len[j].y<len[i].y) { dp[i]=max(dp[j]+len[i].z,dp[i]); } } } int ans=-1; for(int i=0;i<cnt;i++) { ans=max(ans,dp[i]); //cout<<dp[i]<<" "; } //cout<<"\n"; //不能输出dp[cnt-1],因为最后一块可能很矮,只能和前面的几块垒起来,使得它不是最优解 printf("Case %d: maximum height = %d\n",t,ans); //cout<<"\n"; t++; } return 0; }
标签:位置 cout F12 sort for maximum 关联 clu main
原文地址:https://www.cnblogs.com/xxxinnn/p/12990899.html