zoukankan      html  css  js  c++  java
  • POJ 3311Hie with the Pie

        The Pizazz Pizzeria prides itself in delivering pizzas to its customers as fast as possible. Unfortunately, due to cutbacks, they can afford to hire only one driver to do the deliveries. He will wait for 1 or more (up to 10) orders to be processed before he starts any deliveries. Needless to say, he would like to take the shortest route in delivering these goodies and returning to the pizzeria, even if it means passing the same location(s) or the pizzeria more than once on the way. He has commissioned you to write a program to help him.

    大概是给个图,求从0路过所有点再回来的最短路长(当然可以重复)

                          ——by POJ

    http://poj.org/problem?id=3311



        我们可以认为我们现在已经有一条路径了,那么这条路径里显然重复地存在所有点,我们从她中间挑出一份n个点,按她们在路径中的位置排列,则在这个序列中相邻的两点在原路径中的间隔点一定是她们之间的最短路。

        所以这条路径可以看做是由n条(因为是N+1个点)最短路构成的。

        所以可以Floyd最短路,剩下的可以写状压,DP出n个点按什么顺序最优:

        f[i][num](i:当前所在的点;num:当前状态,二进制数,0为没走1为走过)

        f[i][num|k]=f[j][num]+a[j][i]( 前提是num&k==0且这样可以更优)

        这个时候不必考虑可以重复的性质——因为重复的唯一作用是作为两点间的中继点使路径更短,但两点间无论以什么为中继点,都不会比她的最短路短,故不必重复。

        因为懒所以直接写了记忆化

        代码如下:

    #include<cstdio>
    #include<cstring>
    using namespace std;
    int map[11][11];
    long long f[11][4100];
    int n;
    
    void work();
    void floy();
    long long dfs(int ,int );
    
    int main()
    {
        int T;
        scanf("%d",&n);
        while(n)
        {
            work();
            scanf("%d",&n);
        }
        return 0;
    }
    
    void work()
    {
        int i,j,k;
        long long ans=0;
        memset(f,0,sizeof(f));
        for(i=0;i<=n;i++)
            for(j=0;j<=n;j++)
                scanf("%d",&map[i][j]);
        floy();j=2;
        for(i=1;i<=n;i++)
            f[i][j]=map[0][i],j=j<<1;
        ans=dfs(0,j-1);
        printf("%lld
    ",ans);
        return ;
    }
    //f[i][j]=f[k..][l..]+map[k..][i];
    void floy()
    {
        int i,j,k;
        for(k=0;k<=n;k++)
          for(i=0;i<=n;i++)
            for(j=0;j<=n;j++)
              if(map[i][k]&&map[k][j]&&i!=j)
                if(map[i][j]==0||map[i][j]>map[i][k]+map[k][j])
                  map[i][j]=map[i][k]+map[k][j];
    }
    
    long long dfs(int i,int num)
    {
        if(f[i][num])
            return f[i][num];
        int j,k;
        long long l;
        j=1;
        for(k=0;k<=n;k++)
        {
            if(j&num&&k!=i)
            {
                l=dfs(k,num^(1<<i));
                if(f[i][num]>l+map[k][i]||f[i][num]==0)
                   f[i][num]=l+map[k][i];
            }
            j=j<<1;
        }
        return f[i][num];
    }

    祝AC哟;

       

  • 相关阅读:
    021-python基础-python介绍及课程简介
    020-python函数和常用模块-文件操作
    019-python函数和常用模块-内置函数
    018-python基础-三元运算和lambda表达式
    017-python函数和常用模块-函数式编程实现登陆和注册
    016-python函数和常用模块-函数定义和使用
    015-python基础-深浅拷贝
    014-python基础-set集合
    013-python基础-课堂练习
    012-python基础-数据运算
  • 原文地址:https://www.cnblogs.com/nietzsche-oier/p/6296862.html
Copyright © 2011-2022 走看看