zoukankan      html  css  js  c++  java
  • 【DFS】佳佳的魔法阵

    [vijos1284]佳佳的魔法阵

    背景

    也许是为了捕捉猎物(捕捉MM?),也许是因为其它原因,总之,佳佳准备设计一个魔法阵。而设计魔法阵涉及到的最关键问题,似乎就是那些带有魔力的宝石的摆放……

    描述

    魔法阵是一个n*m的格子(高n,宽m),n*m为偶数。佳佳手中有n*m个宝石(以1~n*m编号)。佳佳从最右上角的格子开始走,从一个格子可以走到上、下、左、右4个相邻的格子,但不能走出边界。每个格子必须且仅能到过1次,这样佳佳一共走了n*m个格子停止(随便停哪里)。佳佳每进入一个格子,就在该格子里放入一颗宝石。他是按顺序放的,也就是说——第i个进入的格子放入i号宝石。

    如果两颗宝石的编号对n*m/2取模的值相同,则认为这两颗宝石相互之间有微妙的影响。也就是说,我们按照宝石的编号对n*m/2取模的值,将宝石分成n*m/2对,其中每对都恰有两颗宝石。对于每一对宝石,设第一颗宝石在第a行第b列,另一颗宝石在第c行第d列,那么定义这2个宝石的魔力影响值为 k1*|a-c|+k2*|b-d|。

    需要你求出的是,在所有合乎题意的宝石摆放方案中,所有成对的宝石间的最大魔力影响值的最小值为多少。换句话说,如果我们定义对n*m/2取模的值为i的一对宝石的魔力影响值为a[i]。你需要求出的就是max{a[i]|i=0,1,2...}的最小值。

    格式

    输入格式

    只有一行用空格隔开的4个整数,分别是n、m、k1、k2,n*m<=50,0<k1,k2<=32767。

    输出格式

    只需输出一个整数,即题目所要求的“所有成对的宝石间的最大魔力影响值的最小值”。

    样例1

    样例输入1

    2 2 2 2
    

    样例输出1

    4
    

    限制

    1秒

    来源

    wxsxg

    试题分析:本题需要一个神奇的剪枝,如果现在走到到格子上下或者左右都不可以走,那么直接return;

                  为什么呢?我们可以知道,如果上下都走过,那么之前一定会有一条路径从上面走到下面来,既然已经走到了这两个之间,那么一定有一边已经没圈起来了,而圈起来到那边一定是我们要走的那边,所以怎样以后都出不来了。

    代码

    #include<iostream>
    #include<cstring>
    #include<cstdio>
    #include<algorithm>
    using namespace std;
    inline int read(){
       int x=0,f=1;char c=getchar();
       for(;!isdigit(c);c=getchar()) if(c=='-') f=-1;
       for(;isdigit(c);c=getchar()) x=x*10+c-'0';
       return x*f;      
    }
    int N,M,K1,K2;
    bool vis[51][51];
    int to[1301][2];
    int tmp[1301];
    int res=9999999;
    int dis[5][3]={{-1,0},{1,0},{0,-1},{0,1}};
    void DFS(int step,int a,int b,int ans){
        int f=step%((N*M)/2);
        if(step<=(N*M)/2){
           to[f][0]=a;
           to[f][1]=b;                  
        }
        else{
            ans=max(ans,K1*abs(to[f][0]-a)+K2*abs(to[f][1]-b));
            if(ans>res) return ;
        }
        if(step==N*M){
            res=min(res,ans);
            return ;
        }
        if((vis[a-1][b]==vis[a+1][b])&&(vis[a][b-1]==vis[a][b+1])){
        	bool x=(vis[a-1][b]&vis[a+1][b]),y=(vis[a][b-1]&vis[a][b+1]);
        	if(x!=y) return ;
        	if(x&y) return ;
    	}
    	for(int i=0;i<4;i++){
    		int x=dis[i][1]+b,y=dis[i][0]+a;
    		if(y>N||y<1||x>M||x<1||vis[y][x]) continue;
    		vis[y][x]=true;
    		DFS(step+1,y,x,ans);
    		vis[y][x]=false;
    	}
        return ;
    }
    int main(){
        scanf("%d%d%d%d",&N,&M,&K1,&K2);
        for(int i=0;i<=N;i++) vis[i][0]=vis[N+1][i]=vis[i][M+1]=vis[0][i]=true;
        vis[1][M]=true;
        DFS(1,1,M,0);
        printf("%d
    ",res);
        return 0;
    }
  • 相关阅读:
    Mysql主从复制(基于Log)
    Linux系统开机启动流程
    JS的 验证组织机构的合法性
    Linux以下基于TCP多线程聊天室(client)
    浅谈Java集合框架
    疯狂Java学习笔记(72)-----------大话程序猿面试
    Android自己定义View之组合控件 ---- LED数字时钟
    C/C++学习:函数指针
    springmvc+spring+jpa(hibernate)+redis+maven配置
    数组进行多少次OP操作,才干有序
  • 原文地址:https://www.cnblogs.com/wxjor/p/7026058.html
Copyright © 2011-2022 走看看