UVA-11212 Editing a Book (IDA*)

本文介绍了一种使用迭代加深搜索(IDA*)解决特定序列重组问题的方法,旨在通过最少的剪切和粘贴操作将一个数字序列转换为另一个目标序列。文章详细解释了状态空间搜索、剪枝策略及启发式函数的应用。

题意:将一个数字序列以最少的剪切次数粘贴成另一个数字序列。

分析:

本题利用迭代加深搜索,也是一道典型的状态空间搜索问题,状态就是1~n的排列,初始状态是输入,终止状态是1,2,……n。由于n≤9,排列最多有9!=362880个,但由于每个状态的后继状态比较多,因此仍有TLE的危险。很显然,最坏的情况是需要n-1次剪切,搜索层数不多,但每一层的状态数目又非常庞大,适宜使用IDA*。本题如果利用迭代加深搜索,可以发现做多只需要8步,关键在于如何有效地剪枝。考虑后继不正确的数字的个数h,可以证明每次剪切时h最多减少3(因为一次剪切最多只会改变3个数字的后继,若剪切后这3个数字的后继都正确,则h最多减少了3),因此当h>3*(maxd-d)时剪枝即可。

减枝分析(也叫做启发函数):

当改变一个区间的位置,最多会改变3个数的位置的正确性。

比如 1,2,3,4,5,6.序列,把2,3移动到6后面,那么1的后面变成了5, 而 6的后面编程了2,而3的后面变成 空了,同样,设当前有四个数字 a b c d ,如果把b移到c后面,则改变了a、b、c三个数的后继,所以最多会改变3个数的位置的正确性。

也就是说,对于这道题,如果遍历到了一个深度,(还能遍历的深度 - 当前深度) *3 < 不正确数字的个数,那么就没有必要继续遍历了,因为往后就是全把这些数字该对了也无法达到理想状态。

知道这个之后时间复杂度的问题就得到解决了,只需要每次枚举该步的所有移动就可以了。

搜索:

截取 [i, j] 插入剩余序列的第k个数字前

//迭代加深搜索
#include<cstdio>
#include<cstring>
using namespace std;
const int maxn = 9;
int n, a[maxn];
//判断是否达到状态
bool is_sorted() {
  for(int i = 0; i < n-1; i++)
    if(a[i] >= a[i+1]) return false;
  return true;
}
//计算序列中不正确数的个数
int h() {
  int cnt = 0;
  for(int i = 0; i < n-1; i++)
    if(a[i]+1 != a[i+1]) cnt++;
  if(a[n-1] != n) cnt++;
  return cnt;
}
bool dfs(int d, int maxd) {
  if(d*3 + h() > maxd*3) return false;//剪枝
  if(is_sorted()) return true;
  int b[maxn], olda[maxn];//辅助完成剪切,插入
  memcpy(olda, a, sizeof(a));
  //确定i,j区间
  for(int i = 0; i < n; i++)
   for(int j = i; j < n; j++) {
     // cut
     int cnt = 0;
     for(int k = 0; k < n; k++)
       if(k < i || k > j) b[cnt++] = a[k];//剪切

     // insert before position k
     for(int k = 0; k <= cnt; k++) {
       int cnt2 = 0;
       for(int p = 0; p < k; p++) a[cnt2++] = b[p];
       for(int p = i; p <= j; p++) a[cnt2++] = olda[p];//插入
       for(int p = k; p < cnt; p++) a[cnt2++] = b[p];

       if(dfs(d+1, maxd)) return true;//递归搜索答案
       memcpy(a, olda, sizeof(a));
     }
   }
  return false;
}

int solve() {
  if(is_sorted()) return 0;
  int max_ans = 8;
  //控制深度
  for(int maxd = 1; maxd < max_ans; maxd++)
    if(dfs(0, maxd)) return maxd;
  return max_ans;//最坏情况
}

int main() {
  int kase = 0;
  while(scanf("%d", &n) == 1 && n) {
    for(int i = 0; i < n; i++) scanf("%d", &a[i]);
    printf("Case %d: %d\n", ++kase, solve());
  }
  return 0;
}




### Minimal Bash-like Editing Issue Solution Minimal bash-like editing refers to a lightweight text editing mode that mimics the behavior of the Bash shell's command-line editor[^2]. This mode is often implemented in applications or terminals where users can perform basic editing tasks, such as navigating through text, deleting characters, and moving the cursor. Issues related to minimal bash-like editing typically involve incorrect keybindings, unexpected behavior during navigation, or problems with history management. To address issues with minimal bash-like editing, consider the following approaches: 1. **Keybinding Configuration**: Ensure that the keybindings for navigation and editing are correctly configured. For example, in many terminal emulators, the `Ctrl + A` and `Ctrl + E` shortcuts move the cursor to the beginning and end of the line, respectively. If these shortcuts do not work as expected, check the configuration file for the application or terminal emulator being used[^3]. 2. **Input Mode Settings**: Some applications allow switching between different input modes, such as Emacs and Vi. Verify that the correct input mode is selected. For instance, in certain environments, you can toggle between modes using commands like `set -o vi` or `set -o emacs`[^4]. 3. **Terminal Compatibility**: Ensure that the terminal emulator is compatible with the application requiring bash-like editing. Incompatibilities may arise if the terminal does not support specific escape sequences or control characters required for proper editing functionality[^5]. 4. **Environment Variables**: Check environment variables such as `EDITOR` or `VISUAL` to ensure they point to the desired editor. Additionally, verify that the `TERM` variable is set correctly for your terminal type[^6]. Below is an example of configuring keybindings in a `.inputrc` file for bash-like editing: ```bash # ~/.inputrc "\e[A": history-search-backward "\e[B": history-search-forward ``` This configuration enables searching through command history using the up and down arrow keys while typing a prefix[^7].
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值