UVa OJ 11212 - Editing a Book

UVa OJ 11212 - Editing a Book

(IDA*)

Problem

  你有一篇由n(2≤n≤9)个自然段组成的文章,希望将它们排列成1, 2,…, n。可以用 Ctrl+X(剪切)和Ctrl+V(粘贴)快捷键来完成任务。每次可以剪切一段连续的自然段,粘贴时按照顺序粘贴。注意,剪贴板只有一个,所以不能连续剪切两次,只能剪切和粘贴交替。

  例如,为了将{2,4,1,5,3,6}变为升序,可以剪切1将其放到2前,然后剪切3将其放到4 前。再如,对于排列{3,4,5,1,2},只需一次剪切和一次粘贴即可——将{3,4,5}放在{1,2}后, 或者将{1,2}放在{3,4,5}前。

Input

The input consists of at most 20 test cases. Each case begins with a line containing a single integer n (1 < n < 10), thenumber of paragraphs. The next line contains a permutation of 1, 2, 3, … , n. The last case is followed by a single zero, which should not be processed.

  输入的数据最多有二十种情况。每一种情况以一个整数n开头(1

Output

For each test case, print the case number and the minimal number of cut/paste operations.

输出每一种情况所需要移动的最少步骤。

Sample Input

6
2 4 1 5 3 6
5
3 4 5 1 2
0

Sample Output

Case 1: 2
Case 2: 1

Solution

入门级的迭代加深搜索,题目不复杂,代码也不是很长。主要还是注意当前深度和乐观估计函数到底是什么。

不过虽然是这样说,自己debug的时候也是出了点状况的,比如在进行数据前后的交换时,一开始没注意n的范围,直接把交换的范围取到了9,导致出现莫名其妙的数据错误。orz

嘛,自己毕竟也是刚起步吧,一点点努力吧。下面就把代码贴出来,效率不高,见笑了。

#include <cstdio>
#include <cstring>
using namespace std;

int n,maxd;
int para[10];

int geth(int a[]){
    int num = 0;
    for (int i = 1; i < n;++i)
    if (a[i] + 1 != a[i + 1]) num++;
    return num;
}

void change_para(int i,int j,int k, int a[])
{
    int temp1[10], temp2[10];
    memcpy(temp1, a + i, sizeof(int)*j);
    memcpy(temp2, a + i + j, sizeof(int)*k);
    memcpy(a + i, temp2, sizeof(int)*k);
    memcpy(a + i + k, temp1, sizeof(int)*j);
}

bool isok(int a[]){
    for (int i = 1; i <= n;++i)
        if (i != a[i]) return false;
    return true;
}

bool dfs(int d,int paras[]){
    if (d == maxd )
        if (isok(paras)) return true;

    int h = geth(paras);
    if (3 * d + h <= 3 * maxd)
        for (int i = 1; i < n; ++i)
        for (int j = 1; j <= n - i; ++j)
        for (int k = 1; k <= n+1 - i - j; ++k){
            int new_para[10];
            memcpy(new_para, paras, sizeof(int)*10);
            change_para(i, j, k, new_para);
            if (dfs(d+1, new_para)) return true;
        }
    return false;
}

int main(){
    int cas = 0;
    while (scanf("%d", &n) == 1 && n){
        for (int i = 1; i <= n; ++i)
            scanf("%d", &para[i]);
        for (maxd = 0; maxd < n; ++maxd)
            if (dfs(0,para)) break;
        printf("Case %d: %d\n", ++cas,maxd);
    }
    return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值