Time Limit: 1000MS | Memory Limit: 65536K | |
Total Submissions: 10613 | Accepted: 4396 |
Description
Input
Output
Sample Input
2 10 15 5 1 3 5 10 7 4 9 2 8 5 11 1 2 3 4 5
Sample Output
2 3
题目大意:
给出N个数字,每个数字不大于10000,给出一个S,在N个数字中挑选出连续的a的数字,使这a个数字的和大于或等于S。请问这个a最小是几?
遇到的问题和解题思路:
这道题目是挑战程序设计146页的例题。书上给出了两种解法,不过我稍微改了一下下,但是思路还是一样的。
给出两个代码:
//二分法 #include<cstdio> #include<algorithm> #include<cstring> using namespace std; int a[100000 + 10]; int n, s; void work(){ int sum = 0; for (int i = 0; i < n; i++){ sum += a[i]; a[i] = sum; } //for (int i = 0; i < n; i++)printf(" %d ", a[i]); int res = n + 1; for (int i = 0; a[i] + s <= a[n - 1]; i++){ int tmp = lower_bound(a + i, a + n, a[i] + s) - a - i; //printf("tmp = %d\n", tmp); res = min(res, tmp); } if (res == n + 1)printf("0\n"); else printf("%d\n", res); } int main(){ int t; scanf("%d", &t); while (t--){ memset(a, 0, sizeof(a)); scanf("%d%d", &n, &s); for (int i = 0; i < n; i++)scanf("%d", a + i); work(); } return 0; } //尺取法 #include<cstdio> #include<algorithm> #include<cstring> using namespace std; int n, a[100000 + 10], s; void solve(){ /*for (int i = 0; i < n; i++){ printf("%d ", a[i]); } printf("\n");*/ int left = 0, right = 0, sum = 0, res = n + 1; while (true){ while (right < n && sum < s){ sum += a[right++]; } if (sum < s) break; //printf("mid = %d\n", right - left); res = min(right - left, res); sum -= a[left++]; } if (res < n + 1)printf("%d\n", res); else printf("0\n"); } int main(){ int t; scanf("%d", &t); while(t--){ memset(a, 0, sizeof(a)); scanf("%d%d", &n, &s); for (int i = 0; i < n; i++){ scanf("%d", a + i); } solve(); } return 0; } </cstring></algorithm></cstdio></cstring></algorithm></cstdio>