题目链接:这里
题意:给了n段路,每段路长度不同,你有一辆车最多可以提供E的能量,你的车有四个档,最多换k次档
Assist Level 0 1 2 3
Assist Power 0 4 8 11
0档花费能量0,走的路程长度为0,1档花费1能量,走得最大路程为4…. ,每段路用一个档,如果这个档不能使你走完这段路,那么只能自己蹬,如果超过这段路长度,超过部分不计算到下一段路,意味着下一段路重算,问你蹬车的最短路程是多少?
解法:
最多1000段路,最多换10次档,最大提供能量为50,那么最多的状态为1000*10*50*4 =2e6,搜索所有状态的话2m也够,但是在搜索过程中肯定会挂掉很多状态,这些状态到中途夭折,所以能走到第n段路的状态肯定小于2e6,所以可以广搜,由此总结,可以用状态表示的都可以进行搜索枚举出来,只要状态少,在时间允许内,一般1e6,dp[i][k][e][l]=cost ,表示走到第i段路剩余k次机会,剩余e能量当前用的是l档的最短蹬车路程。

//UVAlive 6908

#include <bits/stdc++.h>
using namespace std;
const int maxn = 1005;
const int inf = 0x3f3f3f3f;
int n, k, e;
int a[maxn];
int dp[maxn][11][55][4];
bool vis[maxn][11][55][4];
int power[4] = {0, 4, 8, 11};
int ans;
struct node{
    int pos, k, e, l;
    node(){}
    node(int pos, int k, int e, int l) : pos(pos), k(k), e(e), l(l) {}
};

void bfs(){
    queue <node> q;
    memset(dp, inf, sizeof(dp));
    memset(vis, 0, sizeof(vis));
    dp[0][k][e][0] = 0;
    vis[0][k][e][0] = 1;
    q.push(node(0, k, e, 0));
    while(!q.empty()){
        node now = q.front(); q.pop();
        int &nowdp = dp[now.pos][now.k][now.e][now.l];
        if(now.pos == n){
            ans = min(ans, nowdp);
            continue;
        }
        if(now.k > 0){//还有换挡的机会&&换挡
            for(int i  = 0; i < 4; i++){
                if(i == now.l || now.e < i) continue;//可用能量小于花费肯定不行,不换挡的情况后面讨论
                node nxt = now;
                nxt.pos++; nxt.k--; nxt.e -= i; nxt.l = i;
                int &nxtdp = dp[nxt.pos][nxt.k][nxt.e][nxt.l];
                int cost = max(0, a[nxt.pos] - power[nxt.l]);
                if(nxtdp > nowdp + cost){
                    nxtdp = nowdp + cost;
                    if(!vis[nxt.pos][nxt.k][nxt.e][nxt.l]){
                        q.push(nxt);
                        vis[nxt.pos][nxt.k][nxt.e][nxt.l] = 1;
                    }
                }
            }
        }
        node nxt = now;
        nxt.pos++;
        if(nxt.e < nxt.l){//能量不够了,直接变成0 挡,不用花费,直接蹬
            nxt.k = 0, nxt.e = 0, nxt.l = 0;
        }
        else{
            nxt.k = now.k, nxt.l = now.l, nxt.e = now.e - now.l;
        }
        int cost = max(0, a[nxt.pos] - power[nxt.l]);
        int &nxtdp = dp[nxt.pos][nxt.k][nxt.e][nxt.l];
        if(nxtdp > nowdp + cost){
            nxtdp = nowdp + cost;
            if(!vis[nxt.pos][nxt.k][nxt.e][nxt.l]){
                q.push(nxt);
                vis[nxt.pos][nxt.k][nxt.e][nxt.l] = 1;
            }
        }
    }
}

int main()
{
    int T, ks = 0;
    scanf("%d", &T);
    while(T--){
        scanf("%d%d%d", &n, &k, &e);
        for(int i = 1; i <= n; i++){
            scanf("%d", &a[i]);
        }
        ans = inf;
        bfs();
        printf("Case #%d: %d\n", ++ks, ans);
    }
    return 0;
}