zoukankan      html  css  js  c++  java
  • [dp]HDOJ4960 Another OCD Patient

    题意: 给一个n, 第二行给n堆的价值v[i], 第三行给a[i].  a[i]表示把i堆合在一起需要的花费.

      求把n堆变成类似回文的 需要的最小花费.

    思路:

    ①记忆化搜索 比较好理解...

     dp[l][r] 记录l到r的最小花费

    枚举对称轴 维护每次l到r之间对称 

    dp[l][r]=min(dp[l][r], a[cur-l]+a[r-i]+dfs(cur+1, i-1));

     l左边和r右边的合并

     1 #include <cstdio>
     2 #include <cstdlib>
     3 #include <cstring>
     4 #include <climits>
     5 #include <cctype>
     6 #include <cmath>
     7 #include <string>
     8 #include <sstream>
     9 #include <iostream>
    10 #include <algorithm>
    11 #include <iomanip>
    12 using namespace std;
    13 #include <queue>
    14 #include <stack>
    15 #include <vector>
    16 #include <deque>
    17 #include <set>
    18 #include <map>
    19 typedef long long LL;
    20 typedef long double LD;
    21 #define pi acos(-1.0)
    22 #define lson l, m, rt<<1
    23 #define rson m+1, r, rt<<1|1
    24 typedef pair<int, int> PI;
    25 typedef pair<int, PI> PP;
    26 #ifdef _WIN32
    27 #define LLD "%I64d"
    28 #else
    29 #define LLD "%lld"
    30 #endif
    31 //#pragma comment(linker, "/STACK:1024000000,1024000000")
    32 //LL quick(LL a, LL b){LL ans=1;while(b){if(b & 1)ans*=a;a=a*a;b>>=1;}return ans;}
    33 //inline int read(){char ch=' ';int ans=0;while(ch<'0' || ch>'9')ch=getchar();while(ch<='9' && ch>='0'){ans=ans*10+ch-'0';ch=getchar();}return ans;}
    34 inline void print(LL x){printf(LLD, x);puts("");}
    35 //inline void read(double &x){char c = getchar();while(c < '0') c = getchar();x = c - '0'; c = getchar();while(c >= '0'){x = x * 10 + (c - '0'); c = getchar();}}
    36 
    37 int a[5005];
    38 LL num[5005];
    39 int cost[5005];
    40 int dp[5005][5005];
    41 int dfs(int l, int r)
    42 {
    43     if(dp[l][r]!=-1)
    44         return dp[l][r];
    45     if(l>=r)
    46         return dp[l][r]=0;
    47     dp[l][r]=cost[r-l];
    48     int cur=l;
    49     for(int i=r;i>=l;i--)
    50     {
    51         for(;cur<i && (num[cur]-num[l-1]<num[r]-num[i-1]);cur++);
    52         if(cur==i)
    53             break;
    54         if(num[cur]-num[l-1]==num[r]-num[i-1])
    55             dp[l][r]=min(dp[l][r], cost[cur-l]+cost[r-i]+dfs(cur+1, i-1));
    56     }
    57     return dp[l][r];
    58 }
    59 int main()
    60 {
    61 #ifndef ONLINE_JUDGE
    62     freopen("in.txt", "r", stdin);
    63     freopen("out.txt", "w", stdout);
    64 #endif
    65     int n;
    66     while(~scanf("%d", &n) && n)
    67     {
    68         num[0]=0;
    69         for(int i=1;i<=n;i++)
    70         {
    71             scanf("%d", &a[i]);
    72             num[i]=num[i-1]+(LL)a[i];
    73         }
    74         for(int i=0;i<n;i++)
    75             scanf("%d", &cost[i]);
    76         for(int i=0;i<=n;i++)
    77             fill(dp[i]+i+1, dp[i]+n+1, -1);
    78         //memset(dp, -1, sizeof(dp));
    79         printf("%d
    ", dfs(1, n));
    80     }
    81     return 0;
    82 }
    HDOJ 4960 记忆化搜索

    ② 区间dp

    结构体里有 SUM和NUM记录 左或右 NUM堆合起来 合成总值为SUM的

    左边从1开始往右 右边从n开始往左

    Lsum==Rsum了就分别把Lsum合起来 Rsum合起来 分别存进L和R   然后继续往中间  

    Ltmp和Rtmp分别记录左边和右边分别合到哪里了

    L R 搞完以后 按顺序把 L 中间 R 放进final (注意中间)

    因为对称 所以只要 dp  final 的一半就够了

    dp[i]=min(dp[i], dp[j]+cost[左个数]+cost[右个数]);

    最后要注意合了 i堆之后 把剩下的全合起来的情况

    ans=min(ans, dp[i]+cost[剩下堆数]);

      1 #include <cstdio>
      2 #include <cstdlib>
      3 #include <cstring>
      4 #include <climits>
      5 #include <cctype>
      6 #include <cmath>
      7 #include <string>
      8 #include <sstream>
      9 #include <iostream>
     10 #include <algorithm>
     11 #include <iomanip>
     12 using namespace std;
     13 #include <queue>
     14 #include <stack>
     15 #include <vector>
     16 #include <deque>
     17 #include <set>
     18 #include <map>
     19 typedef long long LL;
     20 typedef long double LD;
     21 #define pi acos(-1.0)
     22 #define lson l, m, rt<<1
     23 #define rson m+1, r, rt<<1|1
     24 typedef pair<int, int> PI;
     25 typedef pair<int, PI> PP;
     26 #ifdef _WIN32
     27 #define LLD "%I64d"
     28 #else
     29 #define LLD "%lld"
     30 #endif
     31 //#pragma comment(linker, "/STACK:1024000000,1024000000")
     32 //LL quick(LL a, LL b){LL ans=1;while(b){if(b & 1)ans*=a;a=a*a;b>>=1;}return ans;}
     33 //inline int read(){char ch=' ';int ans=0;while(ch<'0' || ch>'9')ch=getchar();while(ch<='9' && ch>='0'){ans=ans*10+ch-'0';ch=getchar();}return ans;}
     34 inline void print(LL x){printf(LLD, x);puts("");}
     35 //inline void read(double &x){char c = getchar();while(c < '0') c = getchar();x = c - '0'; c = getchar();while(c >= '0'){x = x * 10 + (c - '0'); c = getchar();}}
     36 
     37 struct node
     38 {
     39     LL SUM;
     40     int NUM;
     41 }L[5005], R[5005], final[5005];
     42 LL dp[5005];
     43 int a[5005];
     44 int cost[5005];
     45 int Ltop, Rtop, top;
     46 int main()
     47 {
     48 #ifndef ONLINE_JUDGE
     49     freopen("in.txt", "r", stdin);
     50     freopen("out.txt", "w", stdout);
     51 #endif
     52     int n;
     53     while(~scanf("%d", &n) && n)
     54     {
     55         memset(L, 0, sizeof(L));
     56         memset(R, 0, sizeof(R));
     57         memset(final, 0, sizeof(final));
     58         memset(a, 0, sizeof(a));
     59         memset(cost, 0, sizeof(cost));
     60         for(int i=1;i<=n;i++)
     61             scanf("%d", &a[i]);
     62         for(int i=1;i<=n;i++)
     63             scanf("%d", &cost[i]);
     64 
     65         LL Lsum=a[1], Rsum=a[n];
     66         int Lnum=1, Rnum=1;
     67         Ltop=Rtop=0;
     68         int Ltmp=1, Rtmp=n;
     69         for(int i=1, j=n; i<j;)
     70         {
     71             while(Lsum!=Rsum)
     72             {
     73                 if(i==j)
     74                     break;
     75                 if(Lsum<Rsum)
     76                 {
     77                     Lnum++;
     78                     Lsum+=a[++i];
     79                 }
     80                 else if(Rsum<Lsum)
     81                 {
     82                     Rnum++;
     83                     Rsum+=a[--j];
     84                 }
     85             }
     86             if(Lsum==Rsum)
     87             {
     88                 L[Ltop].SUM=Lsum, L[Ltop++].NUM=Lnum;
     89                 R[Rtop].SUM=Rsum, R[Rtop++].NUM=Rnum;
     90                 Lsum=a[++i];
     91                 Rsum=a[--j];
     92                 Lnum=Rnum=1;
     93                 Ltmp=i;
     94                 Rtmp=j;
     95             }
     96         }
     97         top=0;
     98         for(int i=0;i<Ltop;i++)
     99             final[++top]=L[i];
    100         if(Ltmp<=Rtmp)
    101         {
    102             int sum=0;
    103             for(int i=Ltmp;i<=Rtmp;i++)
    104                 sum+=a[i];
    105             final[++top].SUM=sum, final[top].NUM=Rtmp-Ltmp+1;
    106         }
    107         for(int i=Rtop-1;i>=0;i--)
    108             final[++top]=R[i];
    109         for(int i=1;i<=top/2;i++)
    110         {
    111             int tmp1=final[i].NUM, tmp2=final[top-i+1].NUM;
    112             dp[i]=LLONG_MAX;
    113             for(int j=i-1;j>=0;j--)
    114             {
    115                 dp[i]=min(dp[i], dp[j]+cost[tmp1]+cost[tmp2]);
    116                 tmp1+=final[j].NUM;
    117                 tmp2+=final[top-j+1].NUM;
    118             }
    119         }
    120         LL minn=LLONG_MAX;
    121         LL ans=n;
    122         for(int i=0;i<=top/2;i++)
    123         {
    124             minn=min(minn, dp[i]+cost[ans]);
    125             ans-=final[i+1].NUM+final[top-i].NUM;
    126         }
    127         print(minn);
    128     }
    129     return 0;
    130 }
    HDOJ 4960 区间dp
  • 相关阅读:
    Git的常用命令收集
    【Android界面实现】使用ScrollingTabsView实现有滑动标签的ViewPager效果
    android ViewPager中页面延迟加载的实现
    android 项目快速修改包名
    Json详细使用(二) 序列话和反序列话
    Json的详细使用(一)处理数组/List/Map
    C++ stack around variable....错误
    刷题-滑动窗口类型 求连续数组最大值
    C# 动态绘制扇形图;
    C# livechart使用
  • 原文地址:https://www.cnblogs.com/Empress/p/4063818.html
Copyright © 2011-2022 走看看