zoukankan      html  css  js  c++  java
  • Vijos 1451 圆环取数 【区间DP】

    背景

    小K攒足了路费来到了教主所在的宫殿门前,但是当小K要进去的时候,却发现了要与教主守护者进行一个特殊的游戏,只有取到了最大值才能进去Orz教主……

    描述

    守护者拿出被划分为n个格子的一个圆环,每个格子上都有一个正整数,并且定义两个格子的距离为两个格子之间的格子数的最小值。环的圆心处固定了一个指针,一开始指向了圆环上的某一个格子,你可以取下指针所指的那个格子里的数以及与这个格子距离不大于k的格子的数,取一个数的代价即这个数的值。指针是可以转动的,每次转动可以将指针由一个格子转向其相邻的格子,且代价为圆环上还剩下的数的最大值。

    现在对于给定的圆环和k,求将所有数取完所有数的最小代价。

    格式

    输入格式

    输入文件cirque.in的第1行有两个正整数n和k,描述了圆环上的格子数与取数的范围。

    第2行有n个正整数,按顺时针方向描述了圆环上每个格子上的数,且指针一开始指向了第1个数字所在的格子。

    所有整数之间用一个空格隔开,且不超过10000。

    输出格式

    输出文件cirque.out仅包括1个整数,为取完所有数的最小代价。

    样例1

    样例输入1

    6 1
    4 1 2 3 1 3
    

    样例输出1

    21
    

    限制

    对于20%的数据,n≤10,k≤3;
    对于40%的数据,n≤100,k≤10;
    对于60%的数据,n≤500,k≤20;
    对于100%的数据,n≤2000,k≤500;

    时限1s。

    提示

    图片
    如上图所示,第一步不转动指针,取走4、3两个数,代价为7;
    第2步指针顺时针转动2格,圆环上最大数为3,代价为6,取走1、2、3两个数,代价为6;
    第3步指针顺时针转动1格,代价为1,取走剩下的一个数1,代价为1;
    最小代价为7+6+6+1+1=21。

    题目链接:

      https://www.vijos.org/p/1451

    题目大意:

      N个数顺序排成一个圈,指针指向第一个数,目标是把所有数取走(取后数字消失但是位置依然保留)。每次可以同时取指针左右各k格(含指针)

      取一个数的费用是数本身的大小,移动指针的费用是每移动一格花费目前剩余数字最大的。问最小花费。

    题目思路:

      【区间DP】

      根据规则可以发现,取数字的花费是固定的 sum(1~n),所以只用考虑移动的费用。并且移动过程中肯定是边移边取,所以未取的数字都集中在中间。

      首先一开始指针在1的时候肯定把左右两边的k个都取了。接着就破环成链,k+2~n-k是未取的数字。

      dp[i][j]表示从i到j区间全部取完的最小花费,且此时指针指向i-1(dp[i][j]和dp[j][i]方向不同)

      转移方程分为两个,一个是顺着原来的方向移动一格,另一个是移动到另一边,二者取最优。

      预处理出区间最大值即可(nlogn或n2

     1 //
     2 //by coolxxx
     3 /*
     4 #include<iostream>
     5 #include<algorithm>
     6 #include<string>
     7 #include<iomanip>
     8 #include<map>
     9 #include<stack>
    10 #include<queue>
    11 #include<set>
    12 #include<bitset>
    13 #include<memory.h>
    14 #include<time.h>
    15 #include<stdio.h>
    16 #include<stdlib.h>
    17 #include<string.h>
    18 #include<math.h>
    19 //#include<stdbool.h>
    20 #define min(a,b) ((a)<(b)?(a):(b))
    21 #define max(a,b) ((a)>(b)?(a):(b))
    22 #define swap(a,b) ((a)^=(b),(b)^=(a),(a)^=(b))
    23 */
    24 #include<bits/stdc++.h>
    25 #pragma comment(linker,"/STACK:1024000000,1024000000")
    26 #define abs(a) ((a)>0?(a):(-(a)))
    27 #define lowbit(a) (a&(-a))
    28 #define sqr(a) ((a)*(a))
    29 #define mem(a,b) memset(a,b,sizeof(a))
    30 #define eps (1e-8)
    31 #define J 10000
    32 #define mod 1000000007
    33 #define MAX 0x7f7f7f7f
    34 #define PI 3.14159265358979323
    35 #define N 2004
    36 using namespace std;
    37 typedef long long LL;
    38 double anss;
    39 LL aans;
    40 int cas,cass;
    41 int n,m,lll,ans;
    42 int a[N],sum[N];
    43 int maxx[N][N],dp[N][N];
    44 
    45 int main()
    46 {
    47     #ifndef ONLINE_JUDGE
    48     freopen("1.txt","r",stdin);
    49 //    freopen("2.txt","w",stdout);
    50     #endif
    51     int i,j,k,l;
    52     int x,y,z;
    53 //    for(scanf("%d",&cass);cass;cass--)
    54 //    for(scanf("%d",&cas),cass=1;cass<=cas;cass++)
    55 //    while(~scanf("%s",s))
    56     while(~scanf("%d",&n))
    57     {
    58         scanf("%d",&m);
    59         mem(dp,127);mem(maxx,0);sum[0]=0;
    60         for(i=1;i<=n;i++)
    61         {
    62             scanf("%d",&a[i]);
    63             sum[i]=sum[i-1]+a[i];
    64             dp[i][i]=maxx[i][i]=a[i];
    65         }
    66         if(1+m+m>=n)
    67         {
    68             printf("%d
    ",sum[n]);
    69             continue;
    70         }
    71         for(i=1;i<=n;i++)
    72             for(j=i+1;j<=n;j++)
    73                 maxx[i][j]=maxx[j][i]=max(maxx[i][j-1],a[j]);
    74         for(l=1;l<n-m-m;l++)
    75         {
    76             for(i=m+2;i+l<=n-m;i++)
    77             {
    78                 j=i+l;
    79                 dp[i][j]=min(dp[i+1][j]+maxx[i][j],dp[j-1][i]+((i-m-1)+(n-j-m))*maxx[i][j]);
    80             }
    81             for(i=n-m;i-l>=m+2;i--)
    82             {
    83                 j=i-l;
    84                 dp[i][j]=min(dp[i-1][j]+maxx[i][j],dp[j+1][i]+((j-m-1)+(n-i-m))*maxx[i][j]);
    85             }
    86         }
    87         x=max(dp[m+2][n-m],dp[n-m][m+2])+sum[n];
    88         printf("%d
    ",x);
    89     }
    90     return 0;
    91 }
    92 /*
    93 //
    94 
    95 //
    96 */
    View Code
  • 相关阅读:
    Android中Context具体解释 ---- 你所不知道的Context
    JDK6、Oracle11g、Weblogic10 For Linux64Bit安装部署说明
    matplotlib 可视化 —— 定制 matplotlib
    matplotlib 可视化 —— 移动坐标轴(中心位置)
    matplotlib 可视化 —— 移动坐标轴(中心位置)
    matplotlib 可视化 —— 定制画布风格 Customizing plots with style sheets(plt.style)
    matplotlib 可视化 —— 定制画布风格 Customizing plots with style sheets(plt.style)
    指数函数的研究
    指数函数的研究
    指数分布的研究
  • 原文地址:https://www.cnblogs.com/Coolxxx/p/6535762.html
Copyright © 2011-2022 走看看