• 洛谷 P5507 【机关】题解


    题目

    基本思路和算法(A*)大佬们都讲的很详细了(不会的点这里),这里就提供一个小小的但很实用优化。

    离AC只差一步的可以来看看

    《算法竞赛进阶指南》第124页写到“估价函数的估值不能大于未来的实际价值”,但在这题中,稍稍提高一点估值可以大大提高程序运行效

    优化前

    优化后

    优化前后效率快了将近一倍,而优化所做的所有改变就是在估价函数上乘了一个系数

    一般的估价函数:每个旋钮距离目标状态(1)的差值之和除以2(取上整)

    bool operator < (const e &a) const {
          return s + (v >> 1) + (v & 1) > a.s + (a.v >> 1) + (a.v & 1);
    }

    注:

    1、s指当前状态已经操作的次数,v表示每个旋钮距离目标状态的差值之和(估价函数)

    2、加上(v&1)是为了取上整(也许没什么用)

    3、该比较函数写在结构体中,结构体名称为e

    不难发现,这个估价函数是一个很美好的理想状态(每次操作都让两个旋钮向目标状态靠近),但现实中很难达到,可以让估值更准确一些,于是我在 v 上乘一个稍大于1的系数(1.1, 1.2, 1.3)均可(下面代码中写的1.3,因为这个比较快),可以自己调试

    变成这样:

    bool operator < (const e &a) const {
          return s + (v >> 1) * 1.3 + (v & 1) > a.s + (a.v >> 1) * 1.3 + (a.v & 1);
    }

    小小的改变就上效率大大提高,快了将近400ms(数据最大的点快了300ms,虽然巨佬们总用时都不到300ms

    完整代码

    #pragma GCC optimize("Ofast")
    #include <bits/stdc++.h>
    using namespace std;
    #define x now[a[p][now[p]]]
    #define y now[p]
    int tx, a[13][5], k[30000000], to[5] = {0, 2, 3, 4, 1};
    struct e {
    	int s, sum, v, now[13], step[20];
    	bool operator < (const e &a) const {
          return s + (v >> 1) * 1.3 + (v & 1) > a.s + (a.v >> 1) * 1.3 + (a.v & 1);
        }
        inline void change (int p) {
    		x = to[x], tx = x, y = to[y];
    		v += (tx == 2) * 3 - (tx != 2) + (y == 2) * 3 - (y != 2);
        	step[++s] = p, sum += (tx == 1) - (tx == 2) + (y == 1) - (y == 2);
    	}
    	inline int get () {
    		int tmp(0);
    		for (int i = 1; i <= 12; ++i)  tmp = (tmp << 2) + now[i];
    		return tmp;
    	}
    } top, tmp, t;
    void Just_Do_It () {
    	priority_queue <e> q;
    	q.push (top);
    	while (!q.empty()) {
    		tmp = q.top();  q.pop();
    		for (int i = 12; i; --i) {
    			t = tmp;
    			t.change (i);
    			if (t.sum == 12) {
    				printf ("%d
    ", t.s);
    				for (int i = 1; i <= t.s; ++i) printf ("%d ", t.step[i]);
    				return;
    			}
    			int tt (t.get());
    			if (k[tt]) continue;
    			k[tt] = 1;
    			q.push (t);
    		}
    	}
    }
    int main() {
    	for (int i = 1; i <= 12; ++i) 
    		scanf ("%d %d %d %d %d", &top.now[i], &a[i][1], &a[i][2], &a[i][3], &a[i][4]);
    	for (int i = 1; i <= 12; ++i)  
    	  top.sum += (top.now[i] == 1), top.v += (top.now[i] == 1) ? 0 : 5 - i;
    	k[top.get()] = 1;
    	Just_Do_It ();
    	return 0;
    } 
  • 相关阅读:
    Python 中的map函数,filter函数,reduce函数
    编程中,static的用法详解
    C++ list容器系列功能函数详解
    python中的configparser类
    310实验室OTL问题----将写好的C++文件转换成Python文件,并将数据可视化
    310实验室OTL问题
    常量指针、指针常量、指向常量的指针常量
    Iterator迭代器的相关问题
    struts2中action中的通配符
    struts2访问servlet API
  • 原文地址:https://www.cnblogs.com/whx666/p/11409447.html
Copyright © 2020-2023  润新知