kuangbin专题十二 基础dp
1. Max Sum Plus Plus
压缩一维避免超空间,维护前缀最大值将 O ( n 3 ) O(n^3) O(n3)降到 O ( n 2 ) O(n^2) O(n2)。
#include<bits/stdc++.h>
using namespace std;
const int N=1e6+10,INF=0x7fffffff;
int n,m;
int a[N],f[N],Max[N];
int main()
{
while(scanf("%d%d",&m,&n)!=EOF){
for(int i=1;i<=n;i++) scanf("%d",&a[i]);
for(int i=0;i<=n;i++) f[i]=Max[i]=0;
int cur;
for(int j=1;j<=m;j++){
cur=-INF;
for(int i=j;i<=n;i++){
f[i]=max(f[i-1],Max[i-1])+a[i];
Max[i-1]=cur;
cur=max(cur,f[i]);
}
}
printf("%d\n",cur);
}
return 0;
}
2. Ignatius and the Princess IV
感觉像是题目放错了,用数组或者map记录个数就行。
#include<bits/stdc++.h>
#include<unordered_map>
using namespace std;
const int N=1e6+10;
int n,a[N];
unordered_map<int,int> num;
int main()
{
while(scanf("%d",&n)!=EOF){
for(int i=1;i<=n;i++) scanf("%d",&a[i]);
num.clear();
for(int i=1;i<=n;i++){
num[a[i]]++;
if(num[a[i]]>=(n+1)/2){
printf("%d\n",a[i]);
break;
}
}
}
return 0;
}
相邻的HDU 1028刚好是个dp。分别可以用完全背包或分治的做法来做。
#include<bits/stdc++.h>
using namespace std;
const int N=130;
int f[N];
void init(){
f[0]=1;
for(int i=1;i<N;i++)
for(int j=i;j<N;j++)
f[j]+=f[j-i];
}
int main()
{
init();
int n;
while(scanf("%d",&n)!=EOF){
printf("%d\n",f[n]);
}
return 0;
}
#include<bits/stdc++.h>
using namespace std;
const int N=130;
int f[N][N];
int calc(int a,int b){
if(f[a][b]!=-1) return f[a][b];
if(a<1||b<1) return f[a][b]=0;
if(a==1||b==1) return f[a][b]=1;
if(a==b) return f[a][b]=1+calc(a,b-1);
if(a<b) return f[a][b]=calc(a,a);
if(a>b) return f[a][b]=calc(a-b,b)+calc(a,b-1);
}
int main()
{
memset(f,-1,sizeof f);
int n;
while(scanf("%d",&n)!=EOF){
printf("%d\n",calc(n,n));
}
return 0;
}
3. Monkey and Banana
最长上升子序列模型题
#include<bits/stdc++.h>
using namespace std;
const int N=200;
struct Block{
int x,y,z;
bool operator >(const Block &t)const{
if(x!=t.x) return x>t.x;
return y>t.y;
}
};
int f[N];
int n;
int main()
{
int T=0;
while(scanf("%d",&n),n){
vector<Block> v;
for(int i=1;i<=n;i++){
int a,b,c;
scanf("%d%d%d",&a,&b,&c);
v.push_back({
a,b,c});
v.push_back({
a,c,b});
v.push_back({
b,a,c});
v.push_back({
b,c,a});
v.push_back({
c,a,b});
v.push_back({
c,b,a});
}
sort(v.begin(),v.end(),greater<Block>());
int res=0;
for(int i=0;i<v.size();i++){
f[i]=v[i].z;
for(int j=0;j<i;j++){
if(v[i].x<v[j].x&&v[i].y<v[j].y){
f[i]=max(f[i],f[j]+v[i].z);
}
}
res=max(res,f[i]);
}
printf("Case %d: maximum height = %d\n",++T,res);
}
return 0;
}
4. Doing Homework
很巧妙的状压dp。
#include<bits/stdc++.h>
using namespace std;
const int N=16;
struct Subject{
char name[110];
int last,d;
}a[N];
int n;
int f[1<<N],pre[1<<N];
void output(int u){
if(pre[u]!=0) output(pre[u]);
for(int i=0;i<n;i++){
if(u>>i&1^pre[u]>>i&1){
printf("%s\n",a[i].name);
break;
}
}
}
int main()
{
int T;
scanf("%d",&T);
while(T--){
scanf("%d",&n);
for(int i=0;i<n;i++) scanf("%s%d%d",a[i].name,&a[i].last,&a[i].d);
memset(f,0x3f,sizeof f);
f[0]=0;
for(int i=0;i<1<<n;i++){
int sum=0;
for(int j=0;j<n;j++)
if(i>>j&1) sum+=a[j].d;
for(int j=0;j<n;j++){
if(i>>j&1) continue;
int temp=max(0,sum+a[j].d-a[j].last);
int k=i|(1<<j);
if(f[k]>f[i]+temp){
f[k]=f[i]+temp;
pre[k]=i;
}
}
}
printf("%d\n"<

最低0.47元/天 解锁文章
484

被折叠的 条评论
为什么被折叠?



