题目:http://acm.hdu.edu.cn/showproblem.php?pid=4223
题意很简单:n个数,找出连续m个数的最小绝对值。
先来个暴搜(N<=1000)
250MS
代码:
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#define N 1001
int a[N];
int main()
{
int T,n,i,j,min,cnt;
scanf("%d",&T);
cnt = 1;
do
{
scanf("%d",&n);
scanf("%d",&a[0]);
for(i = 1 ; i < n ; ++i)
{
scanf("%d",&a[i]);
a[i] += a[i-1];
}
min = 100000000;
for(i = 0 ; i < n ; ++i)
if(fabs(a[i]) < min)
min = fabs(a[i]);
for(i = 0 ; i < n ; ++i)
for(j = i + 1 ; j < n ; ++j)
if(fabs(a[j] - a[i]) < min)
min = fabs(a[j] - a[i]);
printf("Case %d: %d\n",cnt++,min);
}while(--T);
//system("pause");
return 0;
}
可以改进,改进思路:一个数组(第0个位置放一个多余的0),每个数组元素都存放的是前面所有数的和,然后把这些和从小到达排序。每两个相邻数做差必可得最小值。为什么?因为相邻,所以存在最小;再看连续,因为一个数表示0~i之间的数的和,另一个表示0~j之间的数的和。相减即可得(i+1)~j或者(j+1)~i之间的和。
因此最小和连续都可以得到保证,所以算法正确。
改进代码(15MS):
#include <cstdio>
#include <algorithm>
#define N 1001
using namespace std;
int a[N];
int main()
{
int n,i,T,tmp,min,cnt = 1;
scanf("%d",&T);
do
{
scanf("%d",&n);
a[0] = 0;
for(i = 1 ; i <= n; ++i)
{
scanf("%d",&a[i]);
a[i] += a[i-1];
}
sort(a,a+n+1);
min =10000000;
for(i = 1 ; i <= n; ++i)
{
tmp = a[i] - a[i-1];
if(tmp < min)
{
min = tmp;
if(!min) break;
}
}
printf("Case %d: %d\n",cnt++,min);
}while(--T);
return 0;
}