sdut2169——Sequence (区间DP)

来源:互联网 发布:简单软件赚钱的软件 编辑:程序博客网 时间:2024/05/16 13:58

Sequence 
Time Limit: 1000ms Memory limit: 65536K 
题目描述 
Given an integer number sequence A of length N (1<=N<=1000), we define f(i,j)=(A[i]+A[i+1]+…+A[j])^2 (i<=j). Now you can split the sequence into exactly M (1<=M<= N) succesive parts, and the cost of a part from A[i] to A[j] is f(i,j). The totle cost is the sum of the cost of each part. Please split the sequence with the minimal cost. 
输入 
At the first of the input comes an integer t indicates the number of cases to follow. Every case starts with a line containing N ans M. The following N lines are A[1], A[2]…A[N], respectively. 0<=A[i]<=100 for every 1<=i<=N. 
输出 
For each testcase, output one line containing an integer number denoting the minimal cost of splitting the sequence into exactly M succesive parts. 
示例输入 

5 2 
1 3 2 4 5 
示例输出 
117

将区间分为m段,使得m段的平方和最小。 
我们定义一个Dp数组Dp[i][j]表示以i结尾,分为j段的最小和,那么对于区间[L+1,i],Dp[i][j] = min(Dp[i][j],Dp[L][j-1]+k=L+1ia[k])

设dp【i,j】为前i个数分为j段那么dp【i,j】=min(dp【i,j】,dp【k,j-1】+sigma(a【z】*a【z】)k<z<i

#include <iostream>
#include <cstdio>
#include <cstring>
#include <queue>
#include <cmath>
#include <algorithm>
#include <vector>
#include <map>
#include <string>
#include <stack>
using namespace std;
typedef long long ll;
#define PI 3.1415926535897932
#define E 2.718281828459045
#define INF 0xffffffff//0x3f3f3f3f
#define mod 100000007

const int M=1005;
int n,m;
int cnt;
int sx,sy,sz;
int mp[1000][1000];
int pa[M*10],rankk[M];
int head[M*6],vis[M*100];
int dis[M*100];
ll prime[M*1000];
bool isprime[M*1000];
int lowcost[M],closet[M];
char st1[5050],st2[5050];
int len[M*6];
typedef pair<int ,int> ac;
//vector<int> g[M*10];
ll dp[1000][2000];
int has[10500];
int month[13]= {0,31,59,90,120,151,181,212,243,273,304,334,0};
int dir[8][2]= {{0,1},{0,-1},{-1,0},{1,0},{1,1},{1,-1},{-1,1},{-1,-1}};

void getpri()
{
    ll i;
    int j;
    cnt=0;
    memset(isprime,false,sizeof(isprime));
    for(i=2; i<1000000LL; i++)
    {
        if(!isprime[i])prime[cnt++]=i;
        for(j=0; j<cnt&&prime[j]*i<1000000LL; j++)
        {
            isprime[i*prime[j]]=1;
            if(i%prime[j]==0)break;
        }
    }
}
struct node
{
    int v,w;
    node(int vv,int ww)
    {
        v=vv;
        w=ww;
    }
};
vector<int> g[M*100];
string str[1000];
int bit[50];

ll sum[5000],a[5000];
int main()
{
    int i,j,k,t;
    scanf("%d",&t);
    while(t--)
    {
        memset(dp,0,sizeof(dp));
        memset(sum,0,sizeof(sum));
        scanf("%d%d",&n,&m);
        for(i=1; i<=n; i++)
        {
            scanf("%I64d",&a[i]);
            sum[i]=sum[i-1]+a[i];
            dp[i][1]=sum[i]*sum[i];//前i个分成一块的情况
        }
        
        for(j=2; j<=m; j++) //枚举分块
        {
            for(i=n-(m-j); i>=j; i--) //前i个分成j块,后边还剩m-j块且数目不能超过n
            {
                dp[i][j]=INF;

                //int minx=INF;
                //if(i>m)break;
                for(k=j-1; k<i; k++)//因为至少有一组最少,最少也不能少于j-1,也就是说j-1组最少也要j-1个,k最大为i-1,因为要算搭配dp[i][j]
                {
                   if((sum[i]-sum[k])*(sum[i]-sum[k])<dp[i][j])

                  //或者minx=min(minx,dp[k][j-1]+(sum[i]-sum[k])*(sum[i]-sum[k]));

                 //dp[i][j]=minx;
                    dp[i][j]=min(dp[i][j],dp[k][j-1]+(sum[i]-sum[k])*(sum[i]-sum[k]));
                    //状态压缩 dp[i]=min(dp[i],dp[k]+(sum[i]-sum[k])*(sum[i]-sum[k]));
                }
            }
        }
        printf("%lld\n",dp[n][m]);//I64d在平台上过不了
    }
    return 0;
}

0 0
原创粉丝点击