UESTC Pick The Sticks (背包变形)

该题是15年CCPC的D题,背包变形,昨天队内组队赛和队友搞了出来 。 各种超时,能优化的地方都搞了才勉强过,应该是姿势不太对。

与普通背包唯一的不同之处就是该题的木板可以超出桌面,只要重心在桌面上就行,那么最多只有两个木板超出桌面,那么不妨尽量多的超出(一半在桌子上),为其他木板留出更大的空间。  这样我们就必须增加一维,表示超出桌面的木板个数。  对于每个木板有两种决策:选还是不选。对于选的木板又有两种决策:是否放在边上让其一半超出桌面。

细节参见代码:

#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
typedef long long ll;
const double eps = 1e-6;
const int INF = 1000000000;
const int maxn = 1000 + 5;
const int maxl = 2000 + 5;
int T,n,m,kase=0;
ll d[2][2*maxl][3],w[maxn],v[maxn],L;
int main() {
    scanf("%d",&T);
    while(T--) {
        scanf("%d%lld",&n,&L);
        L *= 2;
        ll ans = 0, u = 0;
        for(int i=0;i<=L;i++)
            for(int k=0;k<3;k++) d[0][i][k] = 0;
        for(int i=1;i<=n;i++) {
            scanf("%lld%lld",&w[i],&v[i]), w[i] *= 2;
            ans = ans>v[i]?ans:v[i];
            for(ll j=0;j<=L;j++) {
                for(int k=0;k<=2;k++) {
                    d[1-u][j][k] = d[u][j][k];
                    if(k > 0 && j >= (w[i]>>1)) d[1-u][j][k] = (d[1-u][j][k]>d[u][j-(w[i]>>1)][k-1]+v[i])?d[1-u][j][k]:d[u][j-(w[i]>>1)][k-1]+v[i];
                    if(j >= w[i]) d[1-u][j][k] = (d[1-u][j][k]> d[u][j-w[i]][k]+v[i])?d[1-u][j][k]: d[u][j-w[i]][k]+v[i];
                }
            }
            u = 1-u;
        }
        ans = (d[u][L][0]>ans)?d[u][L][0]:ans;
        ans = (d[u][L][1]>ans)?d[u][L][1]:ans;
        ans = (d[u][L][2]>ans)?d[u][L][2]:ans;
        printf("Case #%d: %lld\n",++kase,ans);
    }
    return 0;
}


你可能感兴趣的:(dp,uestc,ACM-ICPC)