Max Sum Plus Plus
题目大意:从一串数组中挑选连续m段子数组,使得最后的sum最大。
思路:首先考虑开二维数组,那么动态转移方程为:
dp[i][j]=max(dp[i-1][k]+a[j],dp[i][j-1]+a[j])
其中dp表示枚举到第 j 个数的时候,已经挑选了 i 段子数组,最大的sum值。
那么后面的转移方程:表示该段正在枚举,或者是新的一串子数组。
那么二维太大了,改成一维数组,那么上一个k位置表示 i - 1 段的时候的最大值,因此可以开一个新的数组来表示上一段的最大值。
代码附上:
#include <bits/stdc++.h>
#define int long long
using namespace std;
const int N = 1e6+5;
int n,m;
int a[N];
int dp[N],f[N];//dp[i][j]表示枚举到j恰好有i组
//dp[i][j]=max(dp[i-1][k]+a[j],dp[i][j-1]+a[j]);void solve(){memset(dp,0,sizeof(dp));memset(f,0,sizeof(f));cin>>n;for(int i=1;i<=n;i++)cin>>a[i];int max1;for(int i=1;i<=m;i++){max1=-0x3f3f3f3f3f3f;for(int j=i;j<=n;j++){dp[j]=max(dp[j-1]+a[j],f[j-1]+a[j]);f[j-1]=max1;max1=max(dp[j],max1);}}cout<<max1<<"\n";}signed main(){ios::sync_with_stdio(0),cin.tie(0),cout.tie(0);int t=1;while(cin>>m&&m!=0){solve();}return 0;
}
Monkey and Banana
一块砖头有6种方式去摆放(1,2,3)(1,3,2)(2,1,3)(2,3,1)(3,1,2)(3,2,1)
上面的砖头长(l) ,宽(s)必须分别小于下面的
dp[i]为第i个砖头是最下面的那个砖头时候 可以达到的最大高度
代码附上:
#include <bits/stdc++.h>
#define int long long
using namespace std;
const int N = 1e6+5;
int n;
struct node{int x,y,z;bool operator<(const node &u)const{if(u.x==x){return y<u.y;}return x<u.x;}
};
int dp[N];
vector<node>g;void _main_main(){memset(dp,0,sizeof(dp));g.clear();for(int i=1;i<=n;i++){int x,y,z;cin>>x>>y>>z;g.push_back({x,y,z});g.push_back({x,z,y});g.push_back({y,z,x});g.push_back({y,x,z});g.push_back({z,x,y});g.push_back({z,y,x});}//所有的状态都存上sort(g.begin(),g.end());int ans=0;for(int i=0;i<g.size();i++){dp[i]=g[i].z;for(int j=i-1;j>=0;j--){//枚举前面比它小的长和宽if(g[j].x<g[i].x&&g[j].y<g[i].y&&dp[j]+g[i].z>dp[i]){dp[i]=dp[j]+g[i].z;ans=max(ans,dp[i]);}}}cout<<ans<<"\n";}signed main (){ios::sync_with_stdio(0),cin.tie(0),cout.tie(0);int tt=1;while(cin>>n&&n!=0){cout << "Case " << tt << ": " ;cout<<"maximum height = ";tt++;_main_main();}
}