POJ之01背包系列


poj3624 Charm Bracelet

模板題

沒有要求填滿,所以初始化為0就行

#include<cstdio>
#include<iostream>
using namespace std;
#define N 15010
int n,m,v[N],c[N],f[N];
int main(){
    scanf("%d%d",&n,&m);
    for(int i=1;i<=n;i++) scanf("%d%d",&v[i],&c[i]);
    for(int i=1;i<=n;i++){
        for(int j=m;j>=v[i];j--){
            f[j]=max(f[j],f[j-v[i]]+c[i]);
        }
    }
    printf("%d\n",f[m]);
    return 0;
}

 

poj3628 Bookshelf 2

 

#include<cstdio>
#include<iostream>
using namespace std;
#define N 21000000
int n,m,sum,ans,c[25],f[N];
int main(){
    scanf("%d%d",&n,&m);
    for(int i=1;i<=n;i++) scanf("%d",&c[i]),sum+=c[i];
    for(int i=1;i<=n;i++){
        for(int j=sum;j>=c[i];j--){
            f[j]=max(f[j],f[j-c[i]]+c[i]);
        }
    }
    for(int i=1;i<=sum;i++){
        if(f[i]>=m){
            ans=f[i]-m;break;
        }
    }
    printf("%d\n",ans);
    return 0;
} 

 

 

 

 

poj1745 Divisibility

 

這道題如果取摸后范圍比較小,第二維不大於100,然后記憶化背包(非遞歸搜索),根據能達到的值推能達到的值,衍生出前n個時的所有狀態。

 

#include<cstdio>
#include<iostream>
using namespace std;
#define N 10005
int n,k,c[N];
bool f[N][105];
int main(){
    scanf("%d%d",&n,&k);
    for(int i=0,x;i<n;i++){
        scanf("%d",&x);
        if(x<0) x=-x;
        c[i]=x%k;
    }
    f[0][c[0]]=1;
    for(int i=1;i<n;i++){
        for(int j=0;j<k;j++){
            if(f[i-1][j]){
                f[i][(j+c[i])%k]=1;
                f[i][(j+k-c[i])%k]=1;
            }
        }
    }
    puts(f[n-1][0]?"Divisible":"Not divisible");
    return 0;
} 

 

 

 

 

poj1976  A Mini Locomotive

 

3輛車運貨,共有n堆貨,每輛可以運連續k堆,求最大運貨量

 

保證k*3<=n;也就是說要運貨量最大必須堆數為k。

 

f[i][j]為前j次前i堆最大運貨量的最大運貨量

 

如果i<j*k;那么只能全運

 

第i堆不運:f[i-1][j]

 

第i堆運:f[i-k][j-1]+sum;

 

#include<cstdio>
#include<cstring>
#include<iostream>
using namespace std;
#define N 50010
int n,k,T,s[N],f[N][4];
int main(){
    scanf("%d",&T);
    while(T--){
        memset(f,0,sizeof f);
        scanf("%d",&n);
        for(int i=1;i<=n;i++) scanf("%d",&s[i]),s[i]+=s[i-1];
        scanf("%d",&k);
        for(int i=1;i<=n;i++){
            for(int j=1;j<=3;j++){
                if(i<j*k)
                    f[i][j]=i;
                else
                    f[i][j]=max(f[i-1][j],f[i-k][j-1]+s[i]-s[i-k]);
            }
        }
        printf("%d\n",f[n][3]);
    }
    return 0;
}

 

 

 

 

poj1837 Balance

 

狀態壓縮求方案數

注意要平移數組

 

#include<cstdio>
#include<cstring>
#include<iostream>
using namespace std;
#define p 7500
#define N 21
int n,m,h[N],w[N],f[N][p*2+10];
int main(){
    scanf("%d%d",&m,&n);
    for(int i=0;i<m;i++) scanf("%d",&h[i]);
    for(int i=1;i<=n;i++) scanf("%d",&w[i]);
    f[0][p]=1;
    for(int i=1;i<=n;i++){
        for(int k=0;k<=p<<1;k++){
            if(f[i-1][k]){
                for(int j=0;j<m;j++){
                    f[i][k+h[j]*w[i]]+=f[i-1][k];
                }
            }
        }
    }
    printf("%d\n",f[n][p]);
    return 0;
}

 

 

 

poj1948  Triangular Pastures

 

n個線,組一個三角形,求三角形的最大面積。

 

海倫公式

 

  • formula,p為半周長

 

因為周長已知,知道兩條邊就能確定面積。

 

設f[i][j](i>j),然后確定每一條邊是否加入那個邊,由已知狀態推出未知狀態,隨之更新最大面積。

 

每條邊不可能超過周長的一半。

 

#include<cstdio>
#include<cmath>
#include<iostream>
using namespace std;
#define M 45
#define N 1605
int n,c,a[M];
bool f[N][N];
int ans=-0x7fffffff;
int check(int x,int y){
    double t1=x;
    double t2=y;
    double t3=c-x-y;
    if(t1+t2<t3||t1+t3<t2||t3+t2<t1) return -1.0;
    double t=c*1.0/2.0;
    double res=sqrt(t*(t-t1)*(t-t2)*(t-t3))*100.0;
    return res;
}
int main(){
    scanf("%d",&n);
    for(int i=1;i<=n;i++) scanf("%d",a+i),c+=a[i];
    f[0][0]=1;
    for(int i=1;i<=n;i++){
        for(int j=c>>1;j>=0;j--){
            for(int k=c>>1;k>=j;k--){
                if(j>=a[i]&&f[j-a[i]][k]) f[j][k]=1; 
                if(k>=a[i]&&f[j][k-a[i]]) f[j][k]=1; 
                if(f[j][k]) ans=max(ans,check(j,k)); 
            }
        }
    }
    printf("%d\n",ans);
    return 0;
}

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM