Day1
1.HDU1024
解:
dp[i][j]:选第j个,并且分成i段的最大plus plus
当对于第i个数来说,又2种组合方法:
-
与当前的合并: sum(l1,r1)+sum(l2,r2)+…+sum(li-1,ri-1)+[ sum( li,ri)+a[ j] ]
-
单独成为一段:那么对于新加进来的这个数,可能会对之前维护的dp[i-1]份进行影响,所以dp[i][j]=max(dp[i-1][j-1])+a[j];
所以转移方程为:dp[i][j]=max(dp[i-1][j],dp[i-1][k]) 其中k表示为j-1之前的数
但是考虑到n=1e6,肯定要爆的
一个算法,它的优化一般是采用贪心减少计算量,或者其他方法进行判重处理
可以观察到,假如第i次,它会查找 j-1 之前的维护的数据;假如第i-1次,它会查找j-2之前的维护的数据
也就是说,dp的第二维度其实重复计算了多次,那么,我们可以降为,用另一个一维的数组来储存它的”j-1“的最大值,这里我合并成了2个一维的dp[n][2]。
代码如下:
#include<bits/stdc++.h>
using namespace std;
int cnt=0;
const int N=1e6+11;
const int inf=-10000001;
int a[N];
int n,m;
int dp[N][2];
void solve()
{
int temp;
memset(dp,0,sizeof(dp));
for(int i=1;i<=m;i++)
{
temp=inf;
for(int j=i;j<=n;j++)
{
dp[j][0]=max(dp[j-1][0],dp[j-1][1])+a[j];
dp[j-1][1]=temp;
temp=max(temp,dp[j][0]);
}
}
cout<<temp<<endl;
}
int main()
{
while(cin>>m>>n)
{
for(int i=1;i<=n;i++)
cin>>a[i];
solve();
}
}
2.HDU1029
解:map计数(会卡输入输出,用scanf,printf 或者 加速)
代码如下:
#include<bits/stdc++.h>
using namespace std;
map<int,int>e;
int n;
int ans;
int main()
{
ios::sync_with_stdio(false);
cin.tie(0),cout.tie(0);
while(cin>>n)
{
int x;
e.clear();
for(int i=1;i<=n;i++)
{
cin>>x;
e[x]++;
if(e[x]>=(n+1)/2)
ans=x;
}
cout<<ans<<endl;
}
return 0;
}
3.HDU1069
解:…没什么好说的
代码如下:
#include<bits/stdc++.h>
using namespace std;
struct node
{
int x,y,z;
};
node a[300];
int cnt=0;
int n;
void push(int x,int y,int z)
{
a[++cnt].x=x;
a[cnt].y=y;
a[cnt].z=z;
}
int dp[600];
bool cmp(node x1,node x2)
{
if(x1.x==x2.x)
return x1.y>x2.y;
return x1.x>x2.x;
}
int maxn;
int main()
{
int x,y,z;
int k=0;
while(cin>>n && n)
{
k++;
maxn=0;
cnt=0;
for(int i=1;i<=n;i++)
{
cin>>x>>y>>z;
push(x,y,z);
push(y,x,z);
push(z,y,x);
push(y,z,x);
push(x,z,y);
push(z,x,y);
}
sort(a+1,a+1+cnt,cmp);
memset(dp,0,sizeof(dp));
for(int i=1;i<=cnt;i++)
{
dp[i]=a[i].z;
for(int j=1;j<i;j++)
{
if(a[j].x>a[i].x && a[j].y>a[i].y)
{
dp[i]=max(dp[j]+a[i].z,dp[i]);
}
}
maxn=max(maxn,dp[i]);
}
cout<<"Case "<<k<<": maximum height = ";
cout<<maxn<<endl;
}
}
Day2
1.HDU1087
解:最大不连续子序列
代码如下:
#include<bits/stdc++.h>
using namespace std;
int n;
const int N=1011;
int a[N];
int dp[N];
int ans;
void solve()
{
ans=0;
for(int i=1;i<=n;i++)
{
dp[i]=a[i];
for(int j=1;j<i;j++)
{
if(a[i]>a[j])
{
dp[i]=max(dp[i],dp[j]+a[i]);
}
}
ans=max(dp[i],ans);
}
cout<<ans<<endl;
}
int main()
{
while(cin>>n && n)
{
for(int i=1;i<=n;i++)
cin>>a[i];
memset(dp,0,sizeof(dp));
solve();
}
}
2.HDU1114
解:完全背包
#include<bits/stdc++.h>
using namespace std;
int T,n;
const int N=10011;
const int inf=0x3f3f3f3f;
int w[N],v[N];
int m;
int ans;
int dp[N];
bool flag;
void solve()
{
ans=inf;
for(int i=1;i<=n;i++)
{
for(int j=w[i];j<=m;j++)
{
dp[j]=min(dp[j],dp[j-w[i]]+v[i]);
}
}
if(dp[m]>=inf)
flag=0;
else
flag=1;
// if(flag)
// cout<<ans;
// else
// cout<<"imopssible";
}
int main()
{
int t;
ios::sync_with_stdio(false);
cin.tie(0),cout.tie(0);
cin>>t;
int x;
while(t--)
{
cin>>x>>m;
m-=x;
cin>>n;
memset(dp,inf,sizeof(dp));
dp[0]=0;
for(int i=1;i<=n;i++)
cin>>v[i]>>w[i];
solve();
if(flag)
cout<<"The minimum amount of money in the piggy-bank is "<<dp[m]<<".";
else
cout<<"This is impossible.";
cout<<endl;
}
return 0;
}
3.HDU1176
**解:**有点像记忆化搜索
代码如下:
#include<bits/stdc++.h>
using namespace std;
int n;
const int N=100011;
int dp[N][13];
int t;
int maxn;
int e[N][13];
void solve()
{
for(int i=t-1;i>=0;i--)
{
for(int j=0;j<=10;j++)
{
dp[i][j]+=max(dp[i+1][j],max(dp[i+1][j+1],dp[i+1][j-1]));
}
}
cout<<dp[0][5]<<endl;
}
int main()
{
int x,y;
ios::sync_with_stdio(false);
cin.tie(0);
while(cin>>n && n)
{
t=0;
maxn=0;
memset(dp,0,sizeof(dp));
memset(e,0,sizeof(e));
for(int i=1;i<=n;i++)
{
cin>>x>>y;
t=max(t,y);
dp[y][x]++;
}
solve();
}
return 0;
}
mood: