zoukankan      html  css  js  c++  java
  • HDU 4960:Another OCD Patient

    HDU 4960:Another OCD Patient

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=4960

    题目大意:有$n$个数$v_i$,现要求将相邻的一些数合并使得合并后为回文数列,将$k$个数合并需要代价$a[k]$,一个数只能被合并一次,问最小代价。

    分治+记忆化

    代码如下:

     1 #include <iostream>
     2 #include <cstdio>
     3 #include <cstring>
     4 #define N 5005
     5 using namespace std;
     6 typedef long long ll;
     7 const ll inf=1000000000000000;
     8 ll n,v[N],a[N],pre[N],ans,l,r,dp[N];
     9 ll solve(ll l,ll r){
    10     if(l<1||r>n)return inf;
    11     if(dp[l]!=-1)return dp[l];
    12     ll lt=l--,rt=r++;
    13     dp[lt]=a[lt]+a[n-rt+1];
    14     while(1<=l&&r<=n){
    15         ll L=pre[l],R=pre[n]-pre[r-1];
    16         if(L==R){
    17             dp[lt]=min(dp[lt],a[lt-l]+a[r-rt]+solve(l,r));
    18             l--;
    19         }else if(L>R){
    20             l--;
    21         }else r++;
    22     }
    23     return dp[lt];
    24 }
    25 int main(void){
    26     while(~scanf("%lld",&n)){
    27         if(n==0)break;
    28         memset(dp,-1,sizeof(dp));
    29         for(int i=1;i<=n;++i){
    30             scanf("%lld",&v[i]);
    31             pre[i]=pre[i-1]+v[i];
    32         }
    33         for(int i=1;i<=n;++i)
    34             scanf("%lld",&a[i]);
    35         ans=a[n],l=1,r=n;
    36         while(l<r){
    37             ll L=pre[l],R=pre[n]-pre[r-1];
    38             if(L==R){
    39                 ans=min(ans,solve(l,r)+a[r-l-1]);
    40                 l++;
    41             }else if(L<R){
    42                 l++;
    43             }else r--;
    44         }
    45         printf("%lld
    ",ans);
    46     }
    47 }
  • 相关阅读:
    java 截取pdf
    webService 发送soap请求,并解析返回的soap报文
    常用网址
    扫描文件夹下代码行数
    CodeMIrror 简单使用
    常用 linux 命令(部分)
    windows下RabbitMQ 监控
    一定要写的日志
    创业思路
    10月9日后计划
  • 原文地址:https://www.cnblogs.com/barrier/p/6864005.html
Copyright © 2011-2022 走看看