状态表示f[i][j]:表示在前i个数中选,且包含第i个数,一共j个数的所有集合,属性:max
状态计算:
f【i】【j】:当前已经第j个点在第i个位置,那么第j-1个点与第j个点之间的点数个数应该不大于k,那么假设倒数第二个点 即第j-1个点的下标是t 则 i-k<=t][j]=max(f【i】【j】,f【t】【j-1]+a[i]) t=>(i-k<=t<i)
最后的结果是在n-k+1 ~ n之间选择一个最后一个点取最大值即可,
#include <bits/stdc++.h>
using namespace std;
const int M = 210;
int n, x, k, a[M], f[M][M];
int main()
{
memset(f, -0x3f3f3f, sizeof f);
f[0][0] = 0;
scanf("%d%d%d", &n, &k, &x);
for(int i=1 ; i<=n ; i++)
scanf("%d", &a[i]);
for(int i=1 ; i<=n ; i++)
{
for(int j=1 ; j<=x ; j++)
for(int u=max(i-x, 0) ; u<i ; u++)
f[i][j] = max(f[i][j], f[u][j-1]+a[i]);
}
int res = -1;
for(int i=n-k+1 ; i<=n ; i++)
res = max(res, f[i][x]);
printf("%d", res);
return 0;
}
#include <bits/stdc++.h>
using namespace std;
const int M = 100100;
int sum[M], res[M], n, k;
int main()
{
scanf("%d%d", &n, &k);
for(int i=1 ; i<=n ; i++)
{
int a; scanf("%d", &a);
sum[i] = (sum[i-1]+a)%k;
ans+=res[sum[i]];
res[sum[i]]++;
}
ans+=res[sum[i]];
return 0;
}
既然是简单版,当然是要爆搜啦~
那么如何搜嘞?
由于数据范围应该不坑
所以可以选择一种最为暴力的搜索方式~
PS:算法进阶指南上有,在dfs板块,可自行查阅
#include <cstring>
#include <algorithm>
#include <iostream>
using namespace std;
#define LL long long
const int N=1000010;
LL c[N];
LL a[N];
int main(){
int n;
cin >> n;
LL sum=0;
for(int i=1;i<=n;i++){
cin >> a[i];
sum+=a[i];
}
LL avg=sum/n;
for(int i=2;i<=n;i++){
c[i]=c[i-1]-avg+a[i];
}//ci =ci+1 +avg-ai;
sort(c+1,c+n+1);
LL res=0;
for(int i=1;i<=n;i++){
res+=abs(c[i]-c[(n+1)>>1]);
}
cout << res;
}
题目没写哪道的?囧