题意:给定一个长度为n序列,分成若干个区间,保证每个区间的和相等,求这个最小的和。(n<=10000)
这题主要是数据给水了,可用区间DP或枚举答案
区间DP
#include<iostream>
#include<cmath>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<algorithm>
#define N 10003
#define FOR(i,x,y) for(int i=(x);i<=(y);i++)
#define DOR(i,x,y) for(int i=(x);i>=(y);i--)
using namespace std;
int dp[7003][7003]; //dp[L][R]表示拆分[L,R]区间后每个子区间最小总和
int A[N],S[N];
int main()
{
int M;
scanf("%d",&M);
while(M--)
{
int kase,n;
scanf("%d%d",&kase,&n);
S[0]=0;
FOR(i,1,n)
{
scanf("%d",&A[i]);
S[i]=S[i-1]+A[i];
}
FOR(l,1,n) //枚举区间长度
FOR(L,1,n-l+1) //枚举左端点
{
int R=L+l-1;
dp[L][R]=S[R]-S[L-1];
FOR(k,L,R-1) //劈成[L,k] [k+1,R]两个子区间
{
if(dp[L][k]==S[R]-S[k])
dp[L][R]=min(dp[L][R],dp[L][k]);
if(dp[k+1][R]==S[k]-S[L-1])
dp[L][R]=min(dp[L][R],dp[k+1][R]);
}
}
printf("%d %d\n",kase,dp[1][n]);
}
return 0;
}
模拟
#include<iostream>
#include<cmath>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<algorithm>
#define N 10003
#define FOR(i,x,y) for(int i=(x);i<=(y);i++)
#define DOR(i,x,y) for(int i=(x);i>=(y);i--)
using namespace std;
int A[N],n;
bool check(int k)
{
int sum=0;
FOR(i,1,n)
{
sum+=A[i];
if(sum==k)sum-=k;
}
return !sum;
}
int main()
{
int M;
scanf("%d",&M);
while(M--)
{
int kase,sum=0;
scanf("%d%d",&kase,&n);
FOR(i,1,n)
{
scanf("%d",&A[i]);
sum+=A[i];
}
FOR(i,1,sum) //枚举答案
if(check(i))
{
printf("%d %d\n",kase,i);
break;
}
}
return 0;
}