zoukankan      html  css  js  c++  java
  • hdu--1227--dp

    以为可以做出这个dp 可是就是写不好 这个状态转移方程 fuck

    题意 还是很简单的...  touch    me贴下别人的思路 :----因为 我自己没做出来--传送

    在n个商店中建m个仓库,使各个商店到仓库的路程之和最小,商店到哪个仓库是有选择的,
    总之路程之和要最小!
     
    我还以给的例子来说,这道题的具体思路:
    本来想做个图的,这样更清晰,我辛苦做出来的弄上面无法显示啊!我泪奔啊HDU <wbr>1227 <wbr>Fast <wbr>Food <wbr>(DP),我只能用汉字来说了,考验一下额的汉字表达水平!
    • 仓库要建在商店的位置,也就是说,它一定在某个商店的坐标处
    首先:
    我们可以将一下n个商店的位置存入dis[]数组(这里注意,这里说的是位置,我们可以想象,highway当做一个数轴来看,那么dis[i]就代表第i个商店在数轴上的坐标,就是位置,它不代表距离);
    然后:
    我 们要算出从第i个商店到第j个商店之间建一个仓库之后又增加的距离case[i][j],这里要明白,从第i个商店到第j个商店建一个仓库,这个仓库所建 的位置一定是dis[(i+j)/2],即建在它的中位数处,所以,这个增加值就是case[i][j]=abs(dis[k]-dis[(i+j) /2])(i<=k<=j);
    接下来找dp[i][j];dp[i][j]代表前j个商店建i个仓库的最小距离;
    下面就是最难理解的一步了,动态转移方程的寻找,
    不好理解就在于有多个阶段,每个阶段都有多个状态,每个阶段的初始值都是不确定的,我们要把它初始为一个尽可能大的数,要找dp[i][j],首先dp[i][j]=10000000(尽可能的大);然后找前一个状态,dp[i-1][m]
    为啥是m呢?因为,上一个状态的仓库数是一定的,肯定是比该状态少1,但是商店数就是不确定的了,它最小是
    i-1,最大是j-1,即m的范围就是(i-1<=m<=j-1),找到上个状态后,再加上一个增加值,这个增加值是从m+1
    到j之间建一个仓库所增加的距离,即case[m+1][j];该状态是dp[i-1][m]+case[m+1][j];那么dp[i][j]就是两值得最小,每次m的改变就会将最小的存入dp[i][j],最后一次的更新,得到该状态的最小值;
    这样,我们就找到了状态转移方程
    dp[i][j]=MIN(dp[i-1][m]+case[m+1][j]),(i-1<=m<=j-1);
     
     1 #include<stdio.h>
     2 #include<string.h>
     3 
     4 const int maxn=220;
     5 const int INF=99999999;
     6 
     7 int dis[maxn],dp[maxn][maxn],cost[maxn][maxn];
     8 
     9 int abs(int x){
    10     return x<0?-x:x;
    11 }
    12 
    13 int min(int a,int b){
    14     return a<b?a:b;
    15 }
    16 
    17 int main(){
    18 
    19     //freopen("input.txt","r",stdin);
    20 
    21     int n,k;
    22     int cases=0;
    23     while(scanf("%d%d",&n,&k)){
    24         int i,j,m;
    25         if(n==0 && k==0)
    26             break;
    27         for(i=1;i<=n;i++)
    28             scanf("%d",&dis[i]);
    29         for(i=1;i<=n;i++)
    30             for(j=i;j<=n;j++){
    31                 cost[i][j]=0;
    32                 for(m=i;m<=j;m++)
    33                     cost[i][j]+=abs(dis[m]-dis[(i+j)/2]);
    34             }
    35         for(i=1;i<=n;i++)
    36             dp[1][i]=cost[1][i];
    37         for(i=2;i<=k;i++)
    38             for(j=i;j<=n;j++){
    39                 dp[i][j]=INF;
    40                 for(m=i-1;m<=j-1;m++)
    41                     dp[i][j]=min(dp[i][j],dp[i-1][m]+cost[m+1][j]);
    42             }
    43         printf("Chain %d
    Total distance sum = %d
    
    ",++cases,dp[k][n]);
    44     }
    45     return 0;
    46 }
    View Code

    我还是对于dp[ i ] [ j ]的前一个状态考虑的不周到啊啊 哎。。。

    这题 还是蛮有价值的=-=

     
     
     
     
     
    just follow your heart
  • 相关阅读:
    数组的基本操作
    面向对象
    继承
    JavaBean规范
    JVM内存模型
    数组的排序
    this
    访问控制权限
    数组
    方法的重载
  • 原文地址:https://www.cnblogs.com/radical/p/3879502.html
Copyright © 2011-2022 走看看