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

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();
    }
}
相关推荐
50万马克的面包1 小时前
顺序表和链表_精华知识点_CSDN博客
数据结构·链表
All for pursuit.1 小时前
【回溯-7】494.目标和
数据结构·c++·算法·leetcode
白杨尚青1 小时前
C++入门篇(十三):vector(上)——动态数组:构造、空间增长与迭代器失效
开发语言·c++·笔记·算法·stl
Jasmine_llq1 小时前
《P17461 [GESP202609 八级] 生成树计数》
算法·栈·tarjan 算法·边双连通分量·深度优先搜索 dfs·tarjan 保存当前路径节点·模乘法
Jasmine_llq1 小时前
《P17462 [GESP202609 八级] 末班车》
算法·dijkstra 算法·最大化版本,求最长可行值·建反向图(逆图 / 反转边)·多源 dijkstra 思想·对每个终点单独跑一遍djst·离线预处理 + 在线查询
50万马克的面包1 小时前
数据结构01-数据结构概念与复杂度-博客稿
数据结构
Logic1011 小时前
C语言/数据结构贪心算法题解:字符串趋同——逐位统计最高频率求最小修改代价
c语言·数据结构·贪心算法·字符串·时间复杂度·频率统计·算法题
the3clipse2 小时前
H.265熵编码核心:CABAC自适应二进制算术编码详解——如何将语法元素高效压缩为比特流
人工智能·算法·视频编码·h.265·hevc·cabac·cavlc
CQU_JIAKE2 小时前
10.4【A】
算法
Godspeed Zhao2 小时前
现代智能雷达技术19——算法(5)
算法