標籤:
題目:每次選取連續的若干數位代價
要求選取雖有數位最小代價.
思路:基礎斜率dp題,題解見http://www.cnblogs.com/kuangbin/archive/2012/08/26/2657650.html
/** @author: Cwind*/#pragma comment(linker, "/STACK:102400000,102400000")#include <iostream>#include <map>#include <algorithm>#include <cstdio>#include <cstring>#include <cstdlib>#include <vector>#include <queue>#include <stack>#include <functional>#include <set>#include <cmath>using namespace std;#define IOS std::ios::sync_with_stdio (false);std::cin.tie(0)#define pb push_back#define PB pop_back#define bk back()#define fs first#define se second#define sq(x) (x)*(x)#define eps (1e-6)#define IINF (1<<29)#define LINF (1ll<<59)#define INF (1000000000)#define FINF (1e3)typedef long long ll;typedef unsigned long long ull;typedef pair<int,int> pii;typedef pair<ll,ll> P;const int maxn=5e5+3000;int n,m;int a[maxn];int Q[maxn];int sum[maxn];int dp[maxn];int front,back;int get1(int a,int b){ return dp[b]+sq(sum[b])-dp[a]-sq(sum[a]);}int get2(int a,int b){ return 2*(sum[b]-sum[a]);}int main(){ freopen("/home/files/CppFiles/in","r",stdin); //freopen("test.in","r",stdin); //freopen("test.out","w",stdout); while(cin>>n>>m){ front=back=0; for(int i=1;i<=n;i++){ scanf("%d",&a[i]); sum[i]=sum[i-1]+a[i]; } Q[back++]=0; for(int i=1;i<=n;i++){ while(front+1<back&&get1(Q[front],Q[front+1])<=sum[i]*get2(Q[front],Q[front+1])){ front++; } dp[i]=dp[Q[front]]+sq(sum[i]-sum[Q[front]])+m; while(front+1<back&&get1(Q[back-2],Q[back-1])*get2(Q[back-1],i)>=get1(Q[back-1],i)*get2(Q[back-2],Q[back-1])){ back--; } Q[back++]=i; } printf("%d\n",dp[n]); } return 0;}View Code
HDU 3507(斜率最佳化dp