zoukankan      html  css  js  c++  java
  • AtCoder Grand Contest 004 B

    题意:

    给你长度为n(n<=2000)的一个序列(环),每个位置有一个数值 (1e9)

    你可以翻开这个位置,消耗为这个位置上的数值

    你也可以循环右移一位(n移到1),比如原先你翻开了1,现在移动完成后你翻开的是2

    这个操作消耗为x(1e9)

    问你使所有的位置都翻开需要的最小带价是多少?

    思路:

    一开始想的是用区间dp

    但是这个循环右移次数没办法统计,不可解

    然后就没想出来别的方法。。

    看了题解,简直太妙了

    就是先预处理区间最小值

    然后枚举循环右移的次数

    然后每个位置都可以通过他和他之前长度为l的位置传递过来

    然后就是用这个区间最小值传递到当前位置就可以了

    /* ***********************************************
    Author        :devil
    ************************************************ */
    #include <cstdio>
    #include <cstring>
    #include <iostream>
    #include <algorithm>
    #include <vector>
    #include <queue>
    #include <set>
    #include <map>
    #include <string>
    #include <cmath>
    #include <stdlib.h>
    #define inf 0x3f3f3f3f
    #define LL long long
    #define rep(i,a,b) for(int i=a;i<=b;i++)
    #define dec(i,a,b) for(int i=a;i>=b;i--)
    #define ou(a) printf("%d
    ",a)
    #define pb push_back
    #define mkp make_pair
    template<class T>inline void rd(T &x){char c=getchar();x=0;while(!isdigit(c))c=getchar();while(isdigit(c)){x=x*10+c-'0';c=getchar();}}
    #define IN freopen("in.txt","r",stdin);
    #define OUT freopen("out.txt","w",stdout);
    using namespace std;
    const int mod=1e9+7;
    const int N=2e3+10;
    int n,x,a[N],mi[N][N];
    LL ans;
    int main()
    {
        rd(n),rd(x);
        rep(i,1,n) rd(a[i]),ans+=a[i];
        rep(i,1,n) rep(j,i,n) mi[i][j]=(j==i)?a[i]:min(a[j],mi[i][j-1]);
        rep(l,1,n-1)
        {
            LL now=(LL)l*x;
            rep(i,1,n) now+=(i>l)?mi[i-l][i]:min(mi[1][i],mi[i+n-l][n]);
            ans=min(ans,now);
        }
        printf("%lld
    ",ans);
        return 0;
    }
  • 相关阅读:
    Understand 学习
    2021年1月
    查看所有请求
    DB2日期和时间函数汇总
    .getClass和.class
    继承和实现接口的区别
    java8 stream
    Lambda表达式详解
    SQL语句小知识---XML文件中的 CDATA语法
    Java--mapper.xml中常用SQL标签
  • 原文地址:https://www.cnblogs.com/d-e-v-i-l/p/5843379.html
Copyright © 2011-2022 走看看