hihocoder-1274-高维dp

#1274 : 自行车架

时间限制: 5000ms
单点时限: 1000ms
内存限制: 256MB

描述

小Hi的宿舍楼下有一块用于停自行车的区域。平时自行车都停得非常杂乱,于是楼长打算去买一排自行车架用来停车。自行车架一般有P个槽,每个槽的两侧都可以停入自行车;但是一个槽位同时只能有一侧停入自行车。此外,停入一辆自行车会导致无法在这一侧的附近若干个槽位中停入自行车。

经过调查,这栋宿舍楼的学生共拥有N辆A型自行车、M辆B型自行车和K辆C型自行车。其中A型自行车会导致这一侧的左右各1个槽位不能使用,B型自行车会导致这一侧的左右2个槽位不能使用,C型自行车会导致这一侧的左右3个槽位不能使用。

现给定N、M和K,楼长希望知道P至少要是多少,才能将所有自行车都停入。

如图中所示,P最少为7就可以存放下2辆A型,1辆B型和2辆C型。

输入

每个输入文件包含多组测试数据,在每个输入文件的第一行为一个整数Q,表示测试数据的组数。

每组测试数据为3个整数N、M和K,意义如前文所述。

对于20%的数据,满足0<=N、M、K<=2,Q=100

对于40%的数据,满足0<=N、M、K<=50,Q=100

对于100%的数据,满足0<=N、M、K<=50,1<=Q<=100000

输出

对于每组测试数据,输出一个整数P,表示自行车架至少需要的槽位。

样例输入
4
2 1 2
1 0 0
2 0 2
1 2 2
样例输出
7
1
5
7

#include <bits/stdc++.h>
//#pragma comment(linker, "/STACK:1024000000,1024000000")

using namespace std;

#define ll long long
#define SZ(x) ((int)(x).size()) 
#define ALL(v) (v).begin(), (v).end()
#define foreach(i, v) for (__typeof((v).begin()) i = (v).begin(); i != (v).end(); ++ i)
#define reveach(i, v) for (__typeof((v).rbegin()) i = (v).rbegin(); i != (v).rend(); ++ i) 
#define REP(i,a,n) for ( int i=a; i<int(n); i++ )
#define FOR(i,a,n) for ( int i=n-1; i>= int(a);i-- )
#define lson rt<<1, L, m
#define rson rt<<1|1, m, R
typedef pair<int, int> pii;
typedef pair<ll, ll> pll;
#define mp(x, y) make_pair(x, y)
#define pb(x) push_back(x)
#define fi first
#define se second
#define CLR(a, b) memset(a, b, sizeof(a))
#define Min(a, b) a = min(a, b)
#define Max(a, b) a = max(a, b)
const int maxn = 50 + 7;
const int INF = 0x3f3f3f3f;
int T;
int N, M, K;
int dp[maxn][maxn][maxn][3][3][4];
void ini(){
    CLR(dp, INF);
    dp[0][0][0][0][0][1] = 0;
    dp[1][0][0][0][0][3] = 1;
    dp[0][1][0][1][0][3] = 1;
    dp[0][0][1][2][0][3] = 1;
    REP(i, 0, 51) REP(j, 0, 51) REP(k, 0, 51) REP(li, 0, 3) REP(lj, 0, 3) REP(lk, 1, 4) REP(ad, 0, 3){
        int fi = i, fj = j, fk = k;
        if(ad == 0) fi ++;
        if(ad == 1) fj ++;
        if(ad == 2) fk ++;
        int flk = 3;
        if(ad == 0) Min(dp[fi][fj][fk][ad][lj][flk], dp[i][j][k][li][lj][lk] + max(li, ad) + 2);
        flk = max(1, max(ad, lj) + 2 - lk);
        Min(dp[fi][fj][fk][ad][li][flk], dp[i][j][k][li][lj][lk] + flk);
    }
}
int main(){
#ifdef ac
    freopen("in.txt","r",stdin);
#endif
    //freopen("out.txt","w",stdout);
    scanf("%d", &T);
    ini();
    while(T--){
        scanf("%d%d%d", &N, &M, &K);
        int res = INF;
        REP(li, 0, 3) REP(lj, 0, 3) REP(lk, 1, 4) res = min(res, dp[N][M][K][li][lj][lk]);
        printf("%d\n", res);
    }
    return 0;
}





评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值