题意:有个#字型的棋盘,2行2列,一共24个格。

如图:每个格子是1或2或3,一共8个1,8个2,8个3.

有A~H一共8种合法操作,比如A代表把A这一列向上移动一个,最上面的格会补到最下面。

求:使中心8个格子数字一致的最少步骤,要输出具体的操作步骤及最终中心区域的数字。如果有多个解,输出字典序最小的操作步骤。

分析 : 还是状态空间的搜索,对象就是一个数字序列,判断中心位置是否一样,可以看出如果使用BFS,每一层还是爆炸,所以使用IDA*,关键还是模拟操作和h函数,这里的h函数是这样定义的,可以看出每一次操作,最多给当前局面添加一个符合要求的数字,那就统计一下中心区域最多的相同数字有多少,然后如果8-h > max_depth - cur_depth的话代表最好的情况下都无法解决,剪枝。模拟操作应该就是很白痴的数组转移赋值了,代码很长,很烦,建议看看刘汝佳的代码。

#include<bits/stdc++.h>
using namespace std;
];
int ans_num;
];
bool Is_ok(int *arr)
{
    ];
    ] || temp!=arr[] || temp!=arr[] || temp!=arr[] || temp!=arr[] || temp!=arr[] || temp!=arr[])
        return false;
    return true;
}

inline int h(const int *now)
{
    ];
    memset(cnt, , sizeof(cnt));
    cnt[now[]]++,  cnt[now[]]++,  cnt[now[]]++,
    cnt[now[]]++, cnt[now[]]++, cnt[now[]]++,
    cnt[now[]]++, cnt[now[]]++;
    ], cnt[]);
    ret = max(ret, cnt[]);
    return ret;
}

inline void Change(int *tmp, int one, int two, int three, int four, int five, int six, int seven)
{
    ];
    index[] = one, index[] = two, index[] = three,
    index[] = four, index[] = five, index[] = six;
    index[] = seven;
    int temp = tmp[one];//!
    ; i<; i++)
        tmp[index[i]] = tmp[index[i+]];
    tmp[index[]] = temp;
}

bool DFS(int *now, int cur_depth, int max_depth, int per_dir)
{
     - h(now) > max_depth - cur_depth) return false;
    if(cur_depth >= max_depth) return false;//!?
    ; dir<=; dir++){//!
        ];
        ){
            &&dir==) || (dir==&&per_dir==)) continue;
            &&dir==) || (dir==&&per_dir==)) continue;
            &&dir==) || (dir==&&per_dir==)) continue;
            &&dir==) || (dir==&&per_dir==)) continue;
        }
        ; i<; i++) tmp[i] = now[i];
        int top = cur_depth;
        switch(dir){
            : ans[top]=,,,,,,);break;
            : ans[top]=,,,,,,);break;
            : ans[top]=,,,,,,);break;
            : ans[top]=,,,,,,);break;
            : ans[top]=,,,,,,);break;
            : ans[top]=,,,,,,);break;
            : ans[top]=,,,,,,);break;
            : ans[top]=,,,,,,);break;
        }
        if(Is_ok(tmp)){
            ans[top+] = '\0';
            ans_num = tmp[];
            return true;
        }
        , max_depth, dir)) return true;
    }
    return false;
}
int main(void)
{
    ]) && Init[]){
        ; i<=; i++){
            scanf("%d", &Init[i]);
        }
        if(Is_ok(Init)){
            puts("No moves needed");
            printf(]);
            continue;
        }
        ;
        ){
            , max_depth, )) break;
            max_depth++;
        }
        puts(ans);
        printf("%d\n", ans_num);
    }
    ;
}

刘汝佳代码:

// UVa1343 The Rotation Game
// Rujia Liu
// This solutions uses IDA* instead of BFS described in the book, because it's shorter 8-)
// It's shorter because no need for lookup tables and "automatically" lexicographically smallest solution.
#include<cstdio>
#include<algorithm>
using namespace std;

/*
      00    01
      02    03
04 05 06 07 08 09 10
      11    12
13 14 15 16 17 18 19
      20    21
      22    23
*/

// lines E~H are computed with the help of rev[]
][]={
  { , , ,,,,}, // A
  { , , ,,,,}, // B
  {, , , , , , }, // C
  {,,,,,,}, // D
};

] = {, , , , , , , }; // reverse lines of each line

// center squares
] = {, , , , , , , };

];
];

bool is_final() {
  ; i < ; i++)
    ]]) return false;
  return true;
}

int diff(int target) {
  ;
  ; i < ; i++)
    if(a[center[i]] != target) ans++;
  return ans;
}

inline int h() {
  ), diff()), diff());
}

inline void move(int i) {
  ]];
  ; j < ; j++) a[line[i][j]] = a[line[i][j+]];
  a[line[i][]] = tmp;
}

bool dfs(int d, int maxd) {
  if(is_final()) {
    ans[d] = '\0';
    printf("%s\n", ans);
    return true;
  }
  if(d + h() > maxd) return false;
  ; i < ; i++) {
    ans[d] = 'A' + i;
    move(i);
    , maxd)) return true;
    move(rev[i]);
  }
  return false;
}

int main() {
  ; i < ; i++)
    ; j < ; j++) line[i][j] = line[rev[i]][-j];
  ]) ==  && a[]) {
    ; i < ; i++) scanf("%d", &a[i]);
    ; i < ; i++) ;
    if(is_final()) {
      printf("No moves needed\n");
    } else {
      ; ; maxd++)
        , maxd)) break;
    }
    printf(]);
  }
  ;
}

瞎:遇到这种看起来很烦的题目,还是没有那种敏感性去试想状态空间搜索,一来就是想着如何模拟,然后脑袋一团shit,思路根本没有,所以总结应该很重要了,提供了一个思考的方向在那里,真正应该思考的是如何去实现这道题所对应的模型,而不是乱想。

UVa 1343 The Rotation Game (状态空间搜索 && IDA*)的更多相关文章

  1. UVA 1343 - The Rotation Game-[IDA*迭代加深搜索]

    解题思路: 这是紫书上的一道题,一开始笔者按照书上的思路采用状态空间搜索,想了很多办法优化可是仍然超时,时间消耗大的原因是主要是: 1)状态转移代价很大,一次需要向八个方向寻找: 2)哈希表更新频繁: ...

  2. UVA - 1343 The Rotation Game (BFS/IDA*)

    题目链接 紫书例题. 首先附上我第一次bfs+剪枝TLE的版本: #include<bits/stdc++.h> using namespace std; typedef long lon ...

  3. UVA 1343 The Rotation Game

    题意: 给出图,往A-H方向旋转,使中间8个格子数字相同.要求旋转次数最少,操作序列字典序尽量小. 分析: 用一维数组存24个方格.二维数组代表每个方向对应的7个方格.IDA*剪枝是当8-8个方格中重 ...

  4. UVa 11212 Editing a Book (IDA* && 状态空间搜索)

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

  5. UVa 1343 旋转游戏(dfs+IDA*)

    https://vjudge.net/problem/UVA-1343 题意:如图所示,一共有8个1,8个2和8个3,如何以最少的移动来使得中间8个格子都为同一个数. 思路:状态空间搜索问题. 用ID ...

  6. UVA - 10118Free Candies(记忆化搜索)

    题目:UVA - 10118Free Candies(记忆化搜索) 题目大意:给你四堆糖果,每一个糖果都有颜色.每次你都仅仅能拿随意一堆最上面的糖果,放到自己的篮子里.假设有两个糖果颜色同样的话,就行 ...

  7. 7-10Editing aBook uva11212(迭代加深搜索 IDA*)

    题意:  给出n( 2<=n<=9) 个乱序的数组  要求拍成升序  每次 剪切一段加上粘贴一段算一次  拍成1 2 3 4 ...n即可     求排序次数 典型的状态空间搜索问题   ...

  8. 埃及分数 迭代加深搜索 IDA*

    迭代加深搜索 IDA* 首先枚举当前选择的分数个数上限maxd,进行迭代加深 之后进行估价,假设当前分数之和为a,目标分数为b,当前考虑分数为1/c,那么如果1/c×(maxd - d)< a ...

  9. UVA - 11212 Editing a Book(IDA*算法+状态空间搜索)

    题意:通过剪切粘贴操作,将n个自然段组成的文章,排列成1,2,……,n.剪贴板只有一个,问需要完成多少次剪切粘贴操作可以使文章自然段有序排列. 分析: 1.IDA*搜索:maxn是dfs的层数上限,若 ...

随机推荐

  1. 将Lambda表达式作为参数传递并解析-在构造函数参数列表中使用Lambda表达式

    public class DemoClass { /// <summary> /// 通过Lambda表达式,在构造函数中赋初始值 /// </summary> /// < ...

  2. laravel框架之批刪&全選&全不選&反選

    <!doctype html> <html lang="en"> <head> <meta charset="UTF-8&quo ...

  3. mysql 聚合函数(2)

    平均 svg select avg(sal + IFNULL(comm,0)) as avg_sal from t_emp 总和 sum select sum(sal + IFNULL(comm,0) ...

  4. PostgreSQL-优化之分表

    分表概述 数据库分表,就是把一张表分成多张表,物理上虽然分开了,逻辑上彼此仍有联系. 分表有两种方式:水平分表,即按列分开:垂直分表,即按行分开 优势 1. 查询速度大幅提升 2. 删除数据速度更快 ...

  5. L2-001. 紧急救援(迪杰斯特拉算法)

    L2-001. 紧急救援 时间限制 200 ms 内存限制 65536 kB 代码长度限制 8000 B 判题程序 Standard 作者 陈越 作为一个城市的应急救援队伍的负责人,你有一张特殊的全国 ...

  6. 根据ip获取地理信息.php

    根据ip获取地理信息.php <?php function getIPLoc_sina($queryIP){ $url = 'http://int.dpool.sina.com.cn/iploo ...

  7. [Vue] vue-router-interview

    1.vue-router 怎么重定向页面? 路由中配置 redirect 属性 使用路由的别名来完成重定向 2.vue-router 怎么配置 404 页面? path: '*',放在最后一个 3.切 ...

  8. google浏览器切换成中文

    新浪下载地址:http://down.tech.sina.com.cn/content/40975.html 默认字体好像是西班牙语 1.浏览器地址chrome://settings/language ...

  9. LVS负载均衡常用的工作模式有NAT、DR、和TUN三种,其中DR模式性能最为优越,使用最为广泛。

    一.安装LVS LVS的编译安装参考本站文章:http://www.linuxe.cn/post-192.html,对于LVS这种功能性软件,在生产中用yum安装也是没有问题的. 1 yum inst ...

  10. linux复习2:Fedora17系统的安装和删除

    一.Linux系统下硬盘的基本知识 1.分区命名方案: (1)Linux系统使用字母和数字的组合来指代硬盘分区 (2)Linux系统使用一种更加灵活的命名方案,该命名方案是基于文件的,文件的命名格式为 ...