zoukankan      html  css  js  c++  java
  • 状压DP入门 传球游戏之最小总代价

    本人水平有限,题解不到为处,请多多谅解

    本蒟蒻谢谢大家观看

    题目:

    Problem B: 传球游戏之最小总代价

    Time Limit: 1 Sec  Memory Limit: 128 MB
    Submit: 89  Solved: 43
    [Submit][Status][Web Board]

    Description

    n个人在做传递物品的游戏,编号为1-n。游戏规则是这样的:开始时物品可以在任意一人手上,他可把物品传递给
    其他人中的任意一位;下一个人可以传递给未接过物品的任意一人。即物品只能经过同一个人一次,而且每次传递
    过程都有一个代价;不同的人传给不同的人的代价值之间没有联系;求当物品经过所有n个人后,整个过程的总代
    价是多少。 

    Input

    第一行为n,表示共有n个人(16>=n>=2); 
    以下为n*n的矩阵,第i+1行、第j列表示物品从编号为i的人传递到编号为j的人所花费的代价,
    特别的有第i+1行、第i列为-1(因为物品不能自己传给自己),其他数据均为正整数(<=10000)。 

    Output

    一个数,为最小的代价总和。 

    Sample Input

    2
    -1 9794
    2724 –1

    Sample Output

    2724

    HINT

       f[i][j]表示在当前状态下的以j结尾需要的最小代价总和;

      dis[i][j]表示以i开始,以j结尾的距离;

      读入时可以手动把n=-1给特判掉;

      初始化:for(i=1 to down n)  f[1<<i-1][i]=0;  //表示可以以任意一个数开始,到自身的代价为0。

      转移:f[i][j]=min(f[i][j],f[i^1<<j-1][k]+dis[k][j]);  //表示(上一个状态的最小代价和 + 当前的距离  与 当前状态的最小代价总和)取min;

      结尾:for(i=1 to down (1<<n)-1) ans=min(ans,f[(1<<n)-1][i])  //表示所有状态枚举完时,可以以任意一个数结尾需要的最小代价总和;取min即可

     code:
    #include<bits/stdc++.h>
    using namespace std;
    int n;
    int dis[21][21];
    int ans;
    int f[1<<20][21];
    inline int read(){
         int x=0,f=1;
         char ch=getchar();
         while(ch<'0'||ch>'9'){
             if(ch=='-')
                 f=-1;
             ch=getchar();
         }
         while(ch>='0'&&ch<='9'){
             x=(x<<1)+(x<<3)+(ch^48);
             ch=getchar();
         }
         return x*f;
    }
    
    inline void write(int x){
         char F[200];
         int tmp=x>0?x:-x ;
         if(x<0)putchar('-') ;
         int cnt=0 ;
            while(tmp>0)
            {
                F[cnt++]=tmp%10+'0';
                tmp/=10;
            }
            while(cnt>0)putchar(F[--cnt]) ;
    }
    
    int main()
    {
            n=read();
        if(n!=-1)
        {
            ans=INT_MAX;
            for(int i=1;i<=n;i++)
            {
                for(int j=1;j<=n;j++)
                {
                    dis[i][j]=read();
                }
            }
            memset(f,0x3f,sizeof(f));
            for(int i=1;i<=n;i++)
            f[1<<i-1][i]=0;
            for(int i=1;i<=(1<<n)-1;i++)
            {
                for(int j=1;j<=n;j++)
                {    
                    
                    if(i&1<<j-1)
                    {
                        for(int k=1;k<=n;k++)
                        {
                            if(i&1<<k-1&&j!=k)
                            {
            f[i][j]=min(f[i][j],f[i^1<<j-1][k]+dis[k][j]);
                            }
                        }
                    }
                }
            }
            for(int i=1;i<=n;i++)
                ans=min(ans,f[(1<<n)-1][i]);
            write(ans);
        }
            cout<<endl;
        return 0;    
    } 
     
  • 相关阅读:
    Java第二十五天,多线程之等待唤醒机制
    Java第二十四天,线程安全
    多线程第二十三天,多线程
    Java第二十二天,异常
    数据结构之广义表
    MS Office使用技巧
    标准C++中的String类的使用
    SQL中创建外键约束
    关系数据标准语言SQL之数据查询
    Windows命令
  • 原文地址:https://www.cnblogs.com/nlyzl/p/11307139.html
Copyright © 2011-2022 走看看