【牛牛的跳跳棋】dp解法

题目大意


当棋子位于第 i 个格子时,它的下一步可以移动到[𝑖 − 𝑝𝑖, 𝑖 + 𝑝𝑖]范围内的任意一个格子,每次可以使得一个格子的弹力系数𝑝𝑖 + 1,请输出最小操作次数,以及操作序列


分析


考场上的时候,第一眼看到这道题就想到了dp,并很快定义出了状态——dp[i]表示到达第i格所需的最少操作次数,那么对于每个dp[i],它都可以更新[𝑖 − 𝑝𝑖, 𝑖 + 𝑝𝑖]范围内的dp,进一步思考,我们可以忽略掉往回走的情况,因为对于任意i,若能到达该点,那么它前面的元素也一定被走到过  
综上:用dp[i]更新dp[i+1]到dp[i+a[i]]的值,除此之外,还要考虑对p[i]进行更改的操作,所以要用dp[i]+1更新dp[i+a[i]+1]的值  

用状态转移方程打出dp后,这道题就已经解决了一半,现在需要找出更改序列,而要知道哪些p[i]被更改了,则要先求到从起点到达n+1点的路径,如果从当前点到下一个点的位移为当前p[i]+1的话,证明该点被修改 

借鉴当时学lis时输出序列的方式,定义一个数组pre,用来保存该点的前驱,最后通过n+1一步一步检索即可

代码

#include<bits/stdc++.h>
using namespace std;
const int MAXN = 1e5 + 5;
template<typename item>//方便 
void read(item &x) {
    x = 0;
    int f = 1;
    char c = getchar();
    while(c < '0' || c > '9') {
        if (c == '-') f = -1;
        c = getchar();
    }
    while(c >= '0' && c <= '9') {
        x = (x << 1) + (x << 3) + (c ^ 48);
        c = getchar(); 
    }
    x *= f;
}
int n , a[MAXN] , dp[MAXN] , pre[MAXN] , ans[MAXN] , cnt;
int main() {
    read(n);
    for (int i = 1 ; i <= n ; i ++) {
        read(a[i]);//输入 
    }
    memset(dp , 0x3f , sizeof(dp));//初始成极大值 
    dp[1] = 0;//起点在1 
    for (int i = 1 ; i <= n ; i ++) {
        for (int j = i + 1 ; j <= min(n + 1 , i + a[i]) ; j ++) {//用当前i更新其能到达的点,因为终点在 n+1,所以只需枚举到 min(n + 1 , i + a[i])即可 
            if (dp[j] > dp[i]) {//更新最小值 
                dp[j] = dp[i];
                pre[j] = i;//保存前驱,用以求出序列 
            }
        }
        if (dp[i + a[i] + 1] > dp[i] + 1) {//考虑当前点被施法了的情况,所以能走到 i+a[i]+1这个点 
            dp[i + a[i] + 1] = dp[i] + 1;
            pre[i + a[i] + 1] = i;//同样,记录前驱 
        }
    }
    printf("%d\n", dp[n + 1]);//先输出最少操作几次 
    int x = n + 1;//以终点为开始往回搜路径 
    while(pre[x]) {
        if (a[pre[x]] + pre[x] + 1 == x) {//若这次移动的路程为当前弹力系数 +1的话,证明该点被更改过 
            ans[++ cnt] = pre[x];
        }
        x = pre[x];//继续往前找,直至前驱为零 
    }
    for (int i = cnt ; i >= 1 ; i --) {
        printf("%d ", ans[i]);//输出 
    }
    return 0;
} 

  • 2
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
好的,以下是一个简单的HTML跳棋代码,你可以参考一下: ```html <!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title>跳棋</title> <style type="text/css"> td { width: 50px; height: 50px; border: 1px solid black; text-align: center; vertical-align: middle; font-size: 24px; } .red { background-color: red; color: white; } .black { background-color: black; color: white; } </style> <script type="text/javascript"> var board = []; var selected = null; var redTurn = true; var offset = [[-2, -2], [-2, 2], [2, -2], [2, 2], [-1, -1], [-1, 1], [1, -1], [1, 1]]; function initBoard() { for (var i = 0; i < 10; i++) { board[i] = []; for (var j = 0; j < 9; j++) { if (i < 5) { if ((i + j) % 2 === 0) { board[i][j] = {color: 'black', type: 'pawn'}; } else { board[i][j] = null; } } else if (i === 5) { if (j === 0 || j === 8) { board[i][j] = {color: 'black', type: 'rook'}; } else if (j === 1 || j === 7) { board[i][j] = {color: 'black', type: 'knight'}; } else if (j === 2 || j === 6) { board[i][j] = {color: 'black', type: 'bishop'}; } else if (j === 3) { board[i][j] = {color: 'black', type: 'guard'}; } else if (j === 4) { board[i][j] = {color: 'black', type: 'king'}; } else if (j === 5) { board[i][j] = {color: 'black', type: 'guard'}; } } else if (i > 5) { if ((i + j) % 2 === 0) { board[i][j] = {color: 'red', type: 'pawn'}; } else { board[i][j] = null; } } } } } function drawBoard() { var table = document.createElement('table'); for (var i = 0; i < 10; i++) { var tr = document.createElement('tr'); for (var j = 0; j < 9; j++) { var td = document.createElement('td'); if (board[i][j]) { td.className = board[i][j].color; td.innerHTML = board[i][j].type; } td.addEventListener('click', function() { var row = this.parentNode.rowIndex; var col = this.cellIndex; if (board[row][col] && board[row][col].color === (redTurn ? 'red' : 'black')) { selected = {row: row, col: col}; this.style.backgroundColor = 'yellow'; } else if (selected && canMove(selected.row, selected.col, row, col)) { move(selected.row, selected.col, row, col); selected = null; redTurn = !redTurn; drawBoard(); } }); tr.appendChild(td); } table.appendChild(tr); } document.body.appendChild(table); } function canMove(fromRow, fromCol, toRow, toCol) { var dx = toCol - fromCol; var dy = toRow - fromRow; var piece = board[fromRow][fromCol]; if (toRow < 0 || toRow > 9 || toCol < 0 || toCol > 8) { return false; } if (dx === 0 && dy === 0) { return false; } if (piece.type === 'pawn') { if (piece.color === 'red' && dy < 0) { return false; } else if (piece.color === 'black' && dy > 0) { return false; } if (Math.abs(dx) + Math.abs(dy) !== 1) { return false; } } else if (piece.type === 'rook') { if (dx !== 0 && dy !== 0) { return false; } if (dx === 0) { var step = dy > 0 ? 1 : -1; for (var i = fromRow + step; i !== toRow; i += step) { if (board[i][fromCol]) { return false; } } } else if (dy === 0) { var step = dx > 0 ? 1 : -1; for (var j = fromCol + step; j !== toCol; j += step) { if (board[fromRow][j]) { return false; } } } } else if (piece.type === 'knight') { if (Math.abs(dx) + Math.abs(dy) !== 3 || Math.abs(dx) === 0 || Math.abs(dy) === 0) { return false; } var x = fromCol + dx / 3; var y = fromRow + dy / 3; if (board[y][x]) { return false; } } else if (piece.type === 'bishop') { if (Math.abs(dx) !== Math.abs(dy)) { return false; } var stepX = dx > 0 ? 1 : -1; var stepY = dy > 0 ? 1 : -1; for (var i = fromRow + stepY, j = fromCol + stepX; i !== toRow; i += stepY, j += stepX) { if (board[i][j]) { return false; } } } else if (piece.type === 'guard') { if (piece.color === 'red' && (toRow < 7 || toCol < 3 || toCol > 5)) { return false; } else if (piece.color === 'black' && (toRow > 2 || toCol < 3 || toCol > 5)) { return false; } if (Math.abs(dx) !== 1 || Math.abs(dy) !== 1) { return false; } } else if (piece.type === 'king') { if (piece.color === 'red' && (toRow < 7 || toCol < 3 || toCol > 5)) { return false; } else if (piece.color === 'black' && (toRow > 2 || toCol < 3 || toCol > 5)) { return false; } if (Math.abs(dx) + Math.abs(dy) !== 1) { return false; } } return true; } function move(fromRow, fromCol, toRow, toCol) { board[toRow][toCol] = board[fromRow][fromCol]; board[fromRow][fromCol] = null; } window.onload = function() { initBoard(); drawBoard(); }; </script> </head> <body> </body> </html> ``` 这个代码实现了一个简单的跳棋游戏,包括棋盘的绘制、棋子的移动和规则的判断等功能。你可以将它保存为一个HTML文件,用浏览器打开后即可开始游戏。注意,这只是一个很基础的实现,如果你想要实现更多功能,比如多人对战、人机对战等,还需要进一步完善代码。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值