第九章-竞赛题目选讲-跳舞机

UVA10618 跳舞机 Tango Tango Insurrection

题目

题解

cpp 复制代码
#include<bits/stdc++.h>
using namespace std;
/*
    Up-上- 0  Left-左- 1  Down-下- 2  Right-右- 3
    根据能量消耗, 逆向dp 计算最优选择:目标dp[0][1][3][0]
dp(i,a,b,s)表示踩第i个箭头,左脚在a上,右脚在b上,上一个移动的脚为s
        (s: 0-没有脚移动;1-左脚移动;2-右脚移动)
    
*/
const int UP = 0, LEFT = 1, RIGHT = 2, DOWN = 3;
const int MAXN = 105;
const int INF = 0x3f3f3f3f;//无穷大
int n;
char in[MAXN];//存储输入
int dp[MAXN][4][4][3];
int action[MAXN][4][4][3];//记录决策(压缩存储)
int pos[MAXN];//字符转编号
char foot[] = ".LR";

int move_energy(int from, int to) {// 单脚连续两次移动的能量
    if (from == to) return 3;
    if (from + to == 3) return 7;
    return 5;
} 

int energy(int a, int b, int s, int f, int t, int ta, int tb) {
    // 非法状态判断
    if (ta == tb) return -1;
    if (ta == RIGHT && tb == LEFT) return -1;
    if (a == RIGHT && tb != b) return -1; // 左脚在右箭头上时,右脚不能动
    if (b == LEFT && ta != a) return -1;  // 右脚在左箭头上时,左脚不能动

    // 能量计算
    int e = 0;
    if(f == 0) e = 0;          // 不动
    else if (f != s) e = 1;     // 换脚
    else {                      // 同脚连踩
        if (f == 1) e = move_energy(a, ta);
        else e = move_energy(b, tb);
    }
    return e;
}

void update(int i, int a, int b, int s, int f, int t) {
    int ta = a,tb = b;//ta-左脚新位置 与tb-右脚新位置
    if(f == 1) ta = t;//左脚移动到t
    else if(f == 2) tb = t;//右脚移动到t
    
    int e = energy(a, b, s, f, t, ta, tb);//计算能量消耗
    if (e < 0) return;
    
    //计算能量花费并更新当前dp为最小值
    int cost = dp[i+1][ta][tb][f] + e;
    if (cost < dp[i][a][b][s]){
        dp[i][a][b][s] = cost;
        action[i][a][b][s] = f * 4 + t; // 压缩存储
    }
}

void solve(){
    n = strlen(in);
    memset(dp,0,sizeof(dp));//dp初始化
    memset(action, 0, sizeof(action));//action初始化
    //逆推
    for(int i = n-1;i >= 0;i--){//遍历每个输入
        for(int a = 0;a < 4;a++){ //左脚所在位置
            for(int b = 0;b < 4;b++){//右脚所在位置
                if(a == b) continue;  //不能在同一位置
                for (int s = 0; s < 3;s++){ //上一次移动的是哪只脚(都没动 or 左脚动 or 右脚动)
                    dp[i][a][b][s] = INF;//初始化为无穷大,方便记录最小能量消耗时的状态
                    if(in[i] == '.'){//当前是空拍 '.'
                        update(i,a,b,s,0,0);//不动
                        for (int t = 0;t < 4;t++){//动(左 or 右)脚到t ,为下一步做准备
                            update(i, a, b, s, 1, t);//左脚动
                            update(i, a, b, s, 2, t);//右脚动
                        }
                    }else{
                        int t = pos[in[i]];//当前目标方向
                        update(i, a, b, s, 1, t);//左脚动
                        update(i, a, b, s, 2, t);//右脚动
                    }
                }
            }
        }
    }

    // 输出方案
    int a = LEFT, b = RIGHT, s = 0;
    for (int i = 0; i < n; ++i) {
        int f = action[i][a][b][s] / 4;
        int t = action[i][a][b][s] % 4;
        printf("%c", foot[f]);
        s = f;
        if (f == 1) a = t;
        else if (f == 2) b = t;
    }
    printf("\n");
}
int main(){
    pos['U'] = UP; pos['L'] = LEFT; pos['R'] = RIGHT; pos['D'] = DOWN;
    while(scanf("%s",in) == 1){
        if (in[0] == '#') break;
        solve();
    }
}
相关推荐
颜酱3 小时前
一步步实现字符串计算器:从「转整数」到「带括号与优化」
javascript·后端·算法
CoovallyAIHub1 天前
语音AI Agent编排框架!Pipecat斩获10K+ Star,60+集成开箱即用,亚秒级对话延迟接近真人反应速度!
深度学习·算法·计算机视觉
NineData1 天前
数据库管理工具NineData,一年进化成为数万+开发者的首选数据库工具?
运维·数据结构·数据库
木心月转码ing1 天前
Hot100-Day14-T33搜索旋转排序数组
算法
会员源码网1 天前
内存泄漏(如未关闭流、缓存无限增长)
算法
颜酱1 天前
从0到1实现LFU缓存:思路拆解+代码落地
javascript·后端·算法
颜酱1 天前
从0到1实现LRU缓存:思路拆解+代码落地
javascript·后端·算法
CoovallyAIHub2 天前
Moonshine:比 Whisper 快 100 倍的端侧语音识别神器,Star 6.6K!
深度学习·算法·计算机视觉
CoovallyAIHub2 天前
速度暴涨10倍、成本暴降6倍!Mercury 2用扩散取代自回归,重新定义LLM推理速度
深度学习·算法·计算机视觉