AT2045 Salvage Robots

本文介绍了一种复杂的机器人救援算法,通过设定状态f[i][j][k][t]为最远向左、右、上、下移动的距离,计算矩形内最多能救的机器人数量。采用前缀和辅助转移,优化复杂度,同时处理机器人死亡状态,最终实现高效求解。

传送门

这个题只要想到移动机器人和移动出口是等价的就好做了
考虑设\(f[i][j][k][t]\)为最远向左移动\(i\),向右移动\(j\),向上移动\(k\),向下移动\(t\),这个矩形内最多能救的机器人
转移就记录一个前缀和来辅助转移,这样复杂度就在能通过的范围内了
但是转移还是比较麻烦的,还需要考虑当前状态下哪些机器人是已经死了的
空间有点卡,可以选择开short也可以将第一维滚动
代码:

#include<cstdio>
#include<algorithm>
#include<cstring>
#include<iostream>
#include<queue>
#include<cmath>
using namespace std;
void read(int &x){
    char ch;bool ok;
    for(ok=0,ch=getchar();!isdigit(ch);ch=getchar())if(ch=='-')ok=1;
    for(x=0;isdigit(ch);x=x*10+ch-'0',ch=getchar());if(ok)x=-x;
}
#define rg register
const int maxn=110;
#define max(a,b) ((a)>(b)?(a):(b))
short ans,f[maxn][maxn][maxn][maxn],l[maxn][maxn],r[maxn][maxn];
int n,m,x,y;char s[maxn];
void solve(){
    int le=y-1,rt=m-y,up=x-1,dw=n-x;
    for(rg int i=0;i<=le;i++)
        for(rg int j=0;j<=rt;j++)
            for(rg int k=0;k<=up;k++)
                for(rg int t=0;t<=dw;t++){
                    if(y-i-1>j){
                        int now1=max(x-k,t+1),now2=min(x+t,n-k);
                        f[i+1][j][k][t]=max(f[i+1][j][k][t],f[i][j][k][t]+r[now2][y-i-1]-r[now1-1][y-i-1]);
                    }
                    else f[i+1][j][k][t]=max(f[i+1][j][k][t],f[i][j][k][t]);
                    
                    if(y+j+1+i<=m){
                        int now1=max(x-k,t+1),now2=min(x+t,n-k);
                        f[i][j+1][k][t]=max(f[i][j+1][k][t],f[i][j][k][t]+r[now2][y+j+1]-r[now1-1][y+j+1]);
                    }
                    else f[i][j+1][k][t]=max(f[i][j+1][k][t],f[i][j][k][t]);
                    
                    if(x-k-1>t){
                        int now1=max(y-i,j+1),now2=min(y+j,m-i);
                        f[i][j][k+1][t]=max(f[i][j][k+1][t],f[i][j][k][t]+l[x-k-1][now2]-l[x-k-1][now1-1]);
                    }
                    else f[i][j][k+1][t]=max(f[i][j][k+1][t],f[i][j][k][t]);
                    
                    if(x+t+1+k<=n){
                        int now1=max(y-i,j+1),now2=min(y+j,m-i);
                        f[i][j][k][t+1]=max(f[i][j][k][t+1],f[i][j][k][t]+l[x+t+1][now2]-l[x+t+1][now1-1]);
                    }
                    else f[i][j][k][t+1]=max(f[i][j][k][t+1],f[i][j][k][t]);
                }
    printf("%d\n",f[le][rt][up][dw]);
}
int main(){
    read(n),read(m);
    for(rg int i=1;i<=n;i++){
        scanf("%s",s+1);
        for(rg int j=1;j<=m;j++){
            if(s[j]=='E')x=i,y=j;
            else if(s[j]=='o')l[i][j]=r[i][j]=1;
        }
    }
    for(rg int i=1;i<=n;i++)
        for(rg int j=1;j<=m;j++)
            l[i][j]+=l[i][j-1];
    for(rg int i=1;i<=m;i++)
        for(rg int j=1;j<=n;j++)
            r[j][i]+=r[j-1][i];
    solve();
}

转载于:https://www.cnblogs.com/lcxer/p/10741797.html

<think>好的,我现在需要帮助用户解决如何将未使用的磁盘链(可能是指损坏的磁盘块或未被正确识别的数据块)恢复为文件的问题。用户提到“salvaged 到文件中”,这通常意味着从损坏的存储中提取数据。 首先,回顾用户之前的问题和回答,用户之前询问了关于使用DOS代码页解码短文件名的问题,现在转向了数据恢复,特别是从未使用的链中恢复文件。根据用户提供的引用内容,涉及到了Oracle数据库坏块处理、目录权限、磁盘空间和事务恢复等,但这些可能与当前问题相关度不高,但需要留意是否存在系统层面的存储问题。 用户提到的“未使用的链”可能是指文件系统中未被正确链接或标记为未使用的数据块,或者是磁盘上未被分配但包含有效数据的块。需要明确用户使用的文件系统类型,比如FAT、NTFS、ext4等,因为不同的文件系统恢复方法不同。不过用户之前的讨论涉及FAT,可能当前问题也是关于FAT或其他文件系统的数据恢复。 接下来,结合提供的引用内容,引用[1]提到使用RMAN备份恢复物理坏块,引用[2]提到使用索引提取损坏表的数据,引用[3]涉及权限和磁盘空间问题,引用[4]提到事务恢复后可以访问块。但用户当前的问题不是数据库恢复,而是文件系统的数据恢复,因此可能需要调整思路。 可能的步骤包括: 1. 检查文件系统错误:使用fsck工具(如之前的fsck.fat)检查并修复文件系统结构,可能恢复丢失的链。 2. 使用数据恢复工具:如ddrescue、testdisk、photorec等,从磁盘中提取未链接的数据块。 3. 手动提取数据块:通过十六进制编辑器或dd命令直接读取磁盘块,并保存为文件。 4. 确保权限和空间:如引用[3]提到的权限和磁盘空间问题,需排除这些基础问题。 需要详细说明每个步骤的具体操作,并提供命令示例。同时,注意数据恢复的风险,建议先备份磁盘。此外,用户可能需要了解如何确定未使用的链的位置,可能需要使用文件系统调试工具。 最后,生成相关问题,帮助用户深入理解数据恢复的其他方面。</think>#### 分步解决方案:从未使用的磁盘链中恢复文件 --- ### 一、核心原理 文件系统中的"未使用链"通常指因文件系统元数据损坏(如FAT表损坏、inode丢失)或意外删除导致的数据块未被正确标记为已占用。要恢复这类数据,需通过以下方法直接访问磁盘底层数据: 1. **定位未链接的数据块**:通过文件系统调试工具或磁盘扫描识别游离数据块 2. **提取数据到文件**:使用二进制读写工具将数据块物理内容保存为新文件 3. **修复文件系统元数据**(可选):重建文件链关联(高风险操作,需谨慎) --- ### 二、操作步骤(以Linux/Unix环境为例) #### 步骤1:检查磁盘完整性 ```bash # 检查文件系统错误(以FAT为例,其他文件系统替换fsck.fat) sudo fsck.fat -v /dev/sdX1 # 若发现"lost chains"提示,则存在可恢复的未使用链 ``` #### 步骤2:手动提取未使用链 ```bash # 1. 定位未使用链的起始块号(通过fsck输出或debugfs) # 示例输出:Processing cluster 0x1234 (chain length 5) # 2. 计算块大小(通常为512/4096字节) block_size=$(blockdev --getbsz /dev/sdX1) # 3. 提取指定范围的块到文件(假设起始块号=1234,链长=5) sudo dd if=/dev/sdX1 of=salvaged_data.bin bs=$block_size \ skip=1234 count=5 status=progress ``` #### 步骤3:文件类型修复 ```bash # 使用file命令识别数据类型 file salvaged_data.bin # 若显示"data",尝试强制指定文件类型(例如JPEG) mv salvaged_data.bin salvaged_data.jpg # 使用hexedit手动修复文件头(需专业知识) hexedit salvaged_data.jpg ``` --- ### 三、高级恢复工具 | 工具名称 | 适用场景 | 命令示例 | |----------------|----------------------------|----------------------------------| | **testdisk** | 分区表修复+文件恢复 | `sudo testdisk /dev/sdX` | | **photorec** | 按文件特征扫描恢复 | `sudo photorec /dev/sdX1` | | **debugfs** | ext2/3/4文件系统底层操作 | `sudo debugfs /dev/sdX1` | | **scalpel** | 自定义文件特征精确提取 | `scalpel -c conf/file.conf sdX1` | --- ### 四、关键风险控制 1. **只读模式挂载**: ```bash sudo mount -o ro /dev/sdX1 /mnt ``` 2. **全盘镜像备份**: ```bash sudo dd if=/dev/sdX of=disk.img bs=4M conv=noerror,sync ``` 3. **使用内存盘操作**: ```bash sudo mkdir /mnt/tmpfs && sudo mount -t tmpfs tmpfs /mnt/tmpfs cp salvaged_data.bin /mnt/tmpfs/ ``` --- ### 五、特殊文件系统处理 #### 1. NTFS文件系统(Windows): ```powershell # 使用chkdsk定位丢失链 chkdsk X: /f # 使用WinHex直接编辑簇数据 ``` #### 2. ZFS/BTRFS: ```bash # ZFS数据恢复 sudo zpool scrub pool_name # BTRFS恢复未引用extents sudo btrfs rescue chunk-recover /dev/sdX ``` --- #### 相关问题 1. 如何判断恢复的文件是否完整? 2. 文件系统日志(journal)对数据恢复有何影响? 3. 固态硬盘(SSD)的数据恢复有什么特殊注意事项?
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值