标签:
D - Pick The Sticks
4
3 7
4 1
2 1
8 1
3 7
4 2
2 1
8 4
3 5
4 1
2 2
8 9
1 1
10 3
Sample Output
Case #1: 2
Case #2: 6
Case #3: 11
Case #4: 3
题意:给你一个长度为L的木棍容器,n个长度a[i],价值v[i]的木棍,将木棍放入容器中, 必须满足:木棍的中心在容器范围内
也就是说小木棍可以放在边缘最多伸出一半,问你最大价值是多少。
题解:选木棍就是01背包,不过多了一个状态就是:当前是否有伸出去的木棍 只有三种情况: 没有,伸出1个,伸出2个
我们可以设计:dp[L][3]在长度L内 伸出木棍的情况
但注意滚动数组,及转移的后效。
///1085422276 #include<bits/stdc++.h> using namespace std ; typedef long long ll; #define mem(a) memset(a,0,sizeof(a)) #define meminf(a) memset(a,127,sizeof(a)) #define TS printf("111111\n") #define FOR(i,a,b) for( int i=a;i<=b;i++) #define FORJ(i,a,b) for(int i=a;i>=b;i--) #define READ(a,b,c) scanf("%d%d%d",&a,&b,&c) #define inf 100000 inline ll read() { ll x=0,f=1; char ch=getchar(); while(ch<‘0‘||ch>‘9‘) { if(ch==‘-‘)f=-1; ch=getchar(); } while(ch>=‘0‘&&ch<=‘9‘) { x=x*10+ch-‘0‘; ch=getchar(); } return x*f; } //**************************************** #define maxn 2005 int v,a,n,L; ll dp[4001][3],ans,f[4001][3]; int main(){ int T=read(); int oo=1; while(T--){ scanf("%d%d",&n,&L); memset(f,-1,sizeof(f)); memset(dp,-1,sizeof(dp)); f[0][0]=0; dp[0][0]=0; L*=2; for(int i=1;i<=n;i++){ scanf("%d%d",&a,&v);a*=2; for(int j=0;j<=L;j++){ f[j][0]=dp[j][0]; f[j][1]=dp[j][1]; f[j][2]=dp[j][2]; } for(int j=0;j<=L;j++){ if(j+a<=L&&f[j][0]!=-1) dp[j+a][0]=max(dp[j+a][0],f[j][0]+v); if(j+(a/2)<=L&&f[j][0]!=-1) dp[j+(a/2)][1]=max(dp[j+(a/2)][1],f[j][0]+v); if(j+a<=L&&f[j][1]!=-1) dp[j+a][1]=max(dp[j+a][1],f[j][1]+v); if(j+a<=L&&f[j][2]!=-1) dp[j+a][2]=max(dp[j+a][2],f[j][2]+v); if(j+(a/2)<=L&&f[j][1]!=-1) dp[j+(a/2)][2]=max(dp[j+(a/2)][2],f[j][1]+v); if(a>=L&&f[0][0]!=-1) dp[L][2]=max(dp[L][2],f[0][0]+v); } } ans=-1; // cout<<dp[12][2]<<endl; for(int i=0;i<=L;i++){ ans=max(ans,dp[i][0]); ans=max(ans,dp[i][1]); ans=max(ans,dp[i][2]); } printf("Case #%d: ",oo++); cout<<ans<<endl; } return 0; }
2015南阳CCPC D - Pick The Sticks 背包DP.
标签:
原文地址:http://www.cnblogs.com/zxhl/p/4924250.html