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();
}
}