HDOJ 4223 (DP)
题目: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; }