zoukankan      html  css  js  c++  java
  • P2210 Haywire(A*)

    P2210 Haywire

    题目描述

    Farmer John有N只奶牛,(4 <= N <= 12,其中N是偶数).

    他们建立了一套原生的系统,使得奶牛与他的朋友可以通过由干草保护的线路来进行对话交流.

    每一头奶牛在这个牧场中正好有3个朋友,并且他们必须把自己安排在一排干草堆中.

    一条长L的线路要占用刚好N堆干草来保护线路.

    比如说,如果有两头奶牛分别在草堆4与草堆7中,并且他们是朋友关系,那么我们就需要用3堆干草来建造线路,使他们之间能够联系.

    假设每一对作为朋友的奶牛都必须用一条单独的线来连接,并且我们可以随便地改变奶牛的位置,请计算出我们建造线路所需要的最少的干草堆.

    输入输出格式

    输入格式:

     

    第1行:一个整数N. 为了方便,我们给奶牛用1~N的数字进行编号.

    第2..1+N: 每一行都有三个在1~N中的整数. 第i+1行的数字代表着第i头奶牛的三个朋友的编号。显然,如果奶牛i是奶牛j的三个朋友之一,那么奶牛j也是奶牛i的三个朋友之一.

     

    输出格式:

     

    一个整数,代表着建造线路需要的干草堆数量的最小值.

     

    输入输出样例

    输入样例#1: 复制
    6
    6 2 5
    1 3 4
    4 2 6
    5 3 2
    4 6 1
    1 5 3
    输出样例#1: 复制
    17

    说明

    样例解释: 奶牛最好的排列是6, 5, 1, 4, 2, 3, 这个时候我们只需要17个单位的干草堆.

    #include<bits/stdc++.h>
    
    #define N 20
    
    using namespace std;
    int n,m,ans,cnt;
    int a[N],vis[N],dis[N][N],fri[N][4];
    
    inline int read()
     {
         int x=0,f=1;char c=getchar();
         while(c>'9'||c<'0'){if(x=='-')f=-1;c=getchar();}
         while(c>='0'&&c<='9'){x=x*10+c-'0';c=getchar();}
         return x*f;
     }
    
    inline int abs_(int a){return a<0?-a:a;}
    
    void calc()
    {
        static int pos[N];
        for(int i=1;i<=n;i++) pos[a[i]]=i; 
        int tot=0;memset(dis,0,sizeof dis);
        for(int i=1;i<=n;i++) for(int j=1;j<=3;j++)
        {
            if(dis[i][fri[i][j]] || dis[fri[i][j]][i]) continue; 
            dis[i][fri[i][j]]=dis[fri[i][j]][i]=1;tot+=abs_(pos[i]-pos[fri[i][j]]);
        }ans=min(ans,tot);
    }
    
    void dfs(int k)
    {
        for(int i=1;i<=n;i++)
        {
            if(!vis[i])
            {
                 vis[i]=1;a[k]=i;
                if(k==n) calc();
                dfs(k+1);
                vis[i]=0;
            }    
        }
    }
    
    int main()
    {
        //freopen("ly.in","r",stdin); 
        n=read();
        for(int i=1;i<=n;i++) for(int j=1;j<=3;j++)
        fri[i][j]=read();
        ans=0x3f3f3f3f;dfs(1);
        printf("%d
    ",ans);
        return 0;
    }
    49暴力dfs
    /*
    nowtot:当前总距离; 
    links:已经访问的所有奶牛中,有多少路线没有找到,(即某奶牛的朋友还没有找到); 
    remain:已经访问的所有奶牛中,没有找到的路线的长度总和,(是当前,并不是所有);
    因为每条路线至少是1,所以我们假定所有没找到的路线开始都为1;
    
    每次,remain+links,即当前位置,还没有找到的所有路线都+1(显然); 
    因此remain是我们的方案的下限,即最小的估值(不可能更小了);
    
    其实,这只是个“随机”值,但这个随机值不会让答案错误; 
    */
    #include<bits/stdc++.h>
    
    #define N 20
    
    using namespace std;
    
    int fr[N][5],a[N],pos[N];
    int n,ans,cnt;
    bool vis[N];
    
    void dfs(int x,int nowtot,int links,int remain)
    {
    
        if(x==n+1) ans=min(ans,nowtot);
        if(remain+nowtot >= ans) return;//最优化剪枝
    
        for(int i=1;i<=n;i++)
        {
            if(!pos[i])
            {
                int new_link=3,sum=0;//每个奶牛开始有三个朋友;
                pos[i]=x;//第i个奶牛放在x上; 
                for(int j=1;j<=3;j++)
                {
                    if(pos[fr[i][j]]!=0)
                    {
                        sum+=abs(x-pos[fr[i][j]]);//发现这条路线已经确定;
                        new_link-=2;//friend路线-1,当前奶牛同样-1,总的减2; 
                    }
                }
                dfs(x+1,nowtot+sum,links+new_link,remain+(links+new_link)-sum);
                pos[i]=0;
            }
        }
        return;
    }
    
    int main()
    {
        scanf("%d",&n);
        for(int i=1;i<=n;i++)for(int j=1;j<=3;j++)
        scanf("%d",&fr[i][j]);
        ans=0x3f3f3f3f; dfs(1,0,0,0);
        printf("%d
    ",ans);
        return 0;
    }
  • 相关阅读:
    线段树----hdoj 1754 I here it
    树状数组----poj 2352 stars
    莫队算法
    枚举+深搜----poj 3279 Fliptile
    java 10 -09的作业
    java 09 06 thread-同步代码块-同步方法
    java09-05 join_daemon
    java09 02 Thread-yield 放弃
    java 07 jar
    java 08 作业
  • 原文地址:https://www.cnblogs.com/L-Memory/p/9889236.html
Copyright © 2011-2022 走看看