• 紫书搜索 例题7-12 UVA


    题目链接:

    https://vjudge.net/problem/UVA-1343

    题意:

    数字1,2,3都有八个,求出最少的旋转次数使得图形中间八个数相同。
    旋转规则:对于每一长行或每一长列,每次旋转就是将数据向头的位置移动一位,头上的数放置到尾部。若次数相同,则找出字典序最小旋转次序。
    输入是从上到下,从左向右,注意方向

    题解:

    代码:

     1 #include <bits/stdc++.h>
     2 using namespace std;
     3 typedef long long ll;
     4 #define MS(a) memset(a,0,sizeof(a))
     5 #define MP make_pair
     6 #define PB push_back
     7 const int INF = 0x3f3f3f3f;
     8 const ll INFLL = 0x3f3f3f3f3f3f3f3fLL;
     9 inline ll read(){
    10     ll x=0,f=1;char ch=getchar();
    11     while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
    12     while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();}
    13     return x*f;
    14 }
    15 //////////////////////////////////////////////////////////////////////////
    16 const int maxn = 1e5+10;
    17 
    18 int maxd,ok,a[50];
    19 char ans[maxn];
    20 int line[8][7] = {
    21     {0,2,6,11,15,20,22},
    22     {1,3,8,12,17,21,23},
    23     {10,9,8,7,6,5,4},
    24     {19,18,17,16,15,14,13}
    25 };
    26 
    27 int rev[8] = {5,4,7,6,1,0,3,2}; // 通过A,B,C,D,反推其他方向。指向反向,用来还原现场。  
    28 int final[8] = {6,7,8,11,12,15,16,17}; // 最后答案要求的点  
    29 
    30 void init(){ // 反推方向
    31     for(int i=4; i<8; i++)
    32         for(int j=0; j<=6; j++)
    33             line[i][j] = line[rev[i]][6-j];
    34 }
    35 
    36 bool is_final(){
    37     int k = a[final[0]];
    38     for(int i=1; i<8; i++)
    39         if(a[final[i]]!=k) return false;
    40     return true;
    41 }
    42 
    43 void move(int k){
    44     int tmp = a[line[k][0]];
    45     for(int i=1; i<7; i++)
    46         a[line[k][i-1]] = a[line[k][i]];
    47     a[line[k][6]] = tmp;
    48 }
    49 
    50 int diff(int x){
    51     int cnt = 0;
    52     for(int i=0; i<8; i++)
    53         if(x != a[final[i]])
    54             cnt++;
    55     return cnt;
    56 }
    57 
    58 int h(){ //估值函数  
    59     return min(min(diff(1),diff(2)),diff(3));
    60 }
    61 
    62 void dfs(int cur){
    63     if(is_final()){
    64         ans[cur] = '';
    65         cout << ans << endl;
    66         ok = 1;
    67         return ;
    68     }
    69 
    70     if(cur+h() > maxd) return ; //剪枝
    71     for(int i=0; i<8; i++){
    72         ans[cur] = 'A'+i;
    73         move(i);
    74         dfs(cur+1);
    75         if(ok) return ;
    76         move(rev[i]); // 还原现场  
    77     }
    78 }
    79 
    80 int main(){
    81     init();
    82     while(scanf("%d",&a[0]) && a[0]){
    83         for(int i=1; i<24; i++) a[i]=read();
    84         ok = 0;
    85         if(is_final())
    86             puts("No moves needed");
    87         else{
    88             for(maxd=1; ; maxd++){
    89                 dfs(0);
    90                 if(ok) break;
    91             }
    92         }
    93         cout << a[6] << endl; // 最终的颜色 
    94     }
    95 
    96     return 0;
    97 }
  • 相关阅读:
    SDUSTOJ 1466
    UVa
    51Nod
    UVa
    easyui-启用禁用方法
    设置系统时间
    移除/添加属性
    .net生成二维码图片
    Mysql数据库误删恢复
    js 加减乘除运算
  • 原文地址:https://www.cnblogs.com/yxg123123/p/6827606.html
Copyright © 2020-2023  润新知