C市现在要转移一批罪犯到D市,C市有n名罪犯,按照入狱时间有顺序,另外每个罪犯有一个罪行值,值越大罪越重。现在为了方便管理,市长决定转移入狱时间连续的c名犯人,同时要求转移犯人的罪行值之和不超过t,问有多少种选择的方式(一组测试用例可能包含多组数据,请注意处理)?
第一行数据三个整数:n,t,c(1≤n≤2e5,0≤t≤1e9,1≤c≤n),第二行按入狱时间给出每个犯人的罪行值ai(0≤ai≤1e9)
一行输出答案。
3 100 2 1 2 3
2
//先计算前c个数的累加值sum,之后将指针i指向数组下标c处,指针每前移一位,
//sum-=a[i-c]; sum+=a[i];使效率变为O(n)
#include <iostream>
using namespace std;
int weight[200005];
int main(){
int n, t, c;
while(cin >> n >> t >> c){
int i, sum = 0, cnt = 0;
for(i = 0; i < n; ++i)
cin >> weight[i];
if(c > n) continue;
for(i = 0; i < c; ++i)
sum += weight[i];
if(sum <= t) ++cnt;
for(i = c; i < n; ++i){
sum -= weight[i-c];
sum += weight[i];
if(sum <= t) ++cnt;
}
cout << cnt << endl;
}
return 0;
}
#include<iostream>
#include<vector>
using namespace std;
int main(void){
int n, t, c; //犯人个数,总犯罪值,连续犯人数
while(cin >> n >> t >> c){ //这里是最恶心的,需要自己处理“多个输入测试用例”
vector<int> val(n);
int sum=0, count=0;
for(int i=0; i<n; i++){
cin >> val[i];
if(i<c) sum += val[i];
}
if (sum<=t) count++;
for(int i=0; i+c<n; i++){
sum += val[i+c]-val[i];
if(sum<=t) count++;
}
cout << count <<endl;
}
return 0;
}
这种类似的可以扫描一趟的题目还是挺多的, 常用的技巧是一左一右两个“指针”。可以在O(n)的时间内解决(最**的方法是O(n^2)的暴力)
保持长度为c,一趟扫下来每次判断一下即可
#include <iostream>
#include <cstring>
using namespace std;
const int maxn = 2e5 + 1;
int arr[maxn];
int main(){
int n, t, c;
while(scanf("%d%d%d", &n, &t, &c) == 3){
memset(arr, 0, sizeof(arr));
for(int i=0;i<n;i++) scanf("%d", &arr[i]);
int sum = 0, l = 0, r = c - 1, cnt = 0;
for(int i=l; i<=r; i++) sum += arr[i];
while(r < n){
if(sum <= t) cnt += 1;
r++; l++;
sum = sum + arr[r] - arr[l-1];
}
cout<<cnt<<endl;
}
return 0;
}
#include<iostream>
#include<vector>
using namespace std;
int main()
{
int n,t,c; //犯人个数,总犯罪值,连续犯人数
while(cin >> n >> t >> c){
cin>>n>>t>>c;
vector<int> a(n);
int sum=0,count=0;
for(int i=0;i<n;i++){
cin>>a[i];
if(i<c) sum+=a[i];
}
if(sum<=t) count++;
for(int i=0;i<n-c;i++){
sum+=a[i+c]-a[i];
if(sum<=t) count++;
}
cout<<count<<endl;
}
return 0;
}
while 1:
try:
s1 = raw_input()
s2 = raw_input()
except:
break
n, t, c = map(int, s1.split())
w = map(int, s2.split())
m, s = 0, 0
for i in range(0, n - c + 1):
if i == 0:
for j in range(c):
m += w[j]
else:
m = m - w[i - 1] + w[i + c - 1]
if m <= t:
s += 1
print s
注意 如果返回结果中有空的测试用例,可能是因为没有循环输入参数,我的代码(C++)
#include "iostream"
#include<vector>
using namespace std;
int main()
{
int n,t,c;
while (cin>>n>>t>>c) {
if(c>n || c<0)
return -1;
vector<int> num(n,0);
int m = 0;
while(m<n && cin>>num[m]) m++;
int i = 0,j = 0;
int sum = num[0], count = 1;
int ret = 0;
while(i <= n-c && j < n) {
if(count == c && sum <= t)
ret++;
while(i <= n-c && (count > c || sum > t))
{
sum -= num[i];
i++;
count--;
if(count == c && sum <= t)
ret++;
}
if(j == n-1)
break;
j++;
sum+=num[j];
count++;
}
cout<<ret<<endl;
}
return 0;
}
已经AC
#include <iostream>
#include <vector>
#include <algorithm>
#include <cmath>
#include <iomanip>
using namespace std;
int main(int argc, char** arg){
int n, t, c;
while (cin >> n >> t >> c){
vector<int> a(n);
for (int i = 0; i < n; i++){
cin >> a[i];
}
int result = 0;
int sum = 0;
for (int i = 0; i <c; i++){
sum += a[i];
}
if (sum <= t){
result++;
}
for (int i = c; i < n; i++){
sum -= a[i - c];
sum += a[i];
if (sum <= t){
result++;
}
}
cout << result << endl;
}
return 0;
}
#include<iostream>
#include<vector>
using namespace std;
int main()
{
int n, t, c;
while (cin >> n >> t >> c)
{
int count = 0, at = 0;
vector<int> ai(n, 0);
for (auto &i:ai)
cin >> i;
for (int i = 0; i < c; i++)
at += ai[i];
if (at <= t)
count++;
for (int i = c; i < n; i++)
{
at = at - ai[i - c] + ai[i];
if (at <= t)
count++;
}
cout << count << endl;
}
return 0;
}
import java.util.Scanner;
public class Main {
public static void main(String args[]){
int n,t,c;
Scanner scan = new Scanner(System.in);
while(scan.hasNextInt()){
n=scan.nextInt();
t=scan.nextInt();
c=scan.nextInt();
int[] a=new int[n];
for(int i=0;i<n;i++){
a[i]=scan.nextInt();
}
}
}
public static int xunzhao(int[] a,int c,int t){
int n=a.length;
int count = 0;
int i,j,k;
int sum=0;
for(k=0;k<c;k++){
sum+=a[k];
}
if(sum<=t){
count++;
}
for(i=1;i<n-c+1;i++){
j=i+c-1;
sum=sum-a[i-1]+a[j];
if(sum<=t){
count++;
}
}
System.out.print(count);
return count;
}
}
答案错误:您提交的程序没有通过所有的测试用例
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
int main()
{
int n,t,c,number=0,sum=0;
int i;
int start,end;
while (scanf("%d %d %d",&n,&t,&c)!=EOF)
{
int *arr=new int[n];
start=0;
for (i=0;i<n;i++)
{
scanf("%d",&arr[i]);
if(i<c)
{
sum=sum+arr[i];
}
}
end=c-1;
do{
if(sum<=t)
number++;
sum=sum+arr[end+1]-arr[start];
end++;
start++;
}while(end<n);
printf("%d\n",number);
delete []arr;
}
return 0;
}
import java.util.Scanner;
import java.io.BufferedInputStream;
public class Main {
public static void main(String args[]){
Scanner in=new Scanner(new BufferedInputStream(System.in));
int n=in.nextInt();
int t=in.nextInt();
int c=in.nextInt();
int A[]=new int[n];
int max=0;//记录连续C个数的值
int re=0;//记录结果
for(int i=0;i<n;i++){
int now=in.nextInt();
if(i<c){
max+=now;//前C个数赋给max
}
A[i]=now;
}
if(max<=t){
re=1;
}
for(int i=c;i<n;i++){
if((A[i]+max-A[i-c])<=t){
max=A[i]+max-A[i-c];
re++;
}
}
System.out.println(re);
in.close();
}
}
import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.io.IOException;
public class Main {
public static void main(String[] args) throws IOException {
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
String line;
while((line = br.readLine()) != null) {
String[] params = line.trim().split(" ");
int n = Integer.parseInt(params[0]);
int t = Integer.parseInt(params[1]);
int c = Integer.parseInt(params[2]);
String[] strArr = br.readLine().trim().split(" ");
int[] arr = new int[n];
long[] calSum = new long[n]; // 构建前缀和数组
for(int i = 0; i < n; i++){
if(i == 0){
arr[i] = Integer.parseInt(strArr[i]);
calSum[i] = arr[i];
}else{
arr[i] = Integer.parseInt(strArr[i]);
calSum[i] = calSum[i - 1] + arr[i];
}
}
int count = 0;
for(int i = -1; i < n - c; i++)
if(calSum[i + c] - (i >= 0? calSum[i]: 0) <= t) count ++;
System.out.println(count);
}
}
} import java.util.Scanner;
public class Main {
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
while (sc.hasNext()) {
int n = sc.nextInt();
int t = sc.nextInt();
int c = sc.nextInt();
int[] arr = new int[n];
int count = 0;
int temSum = 0;
for (int i = 0; i < c; i++) {
arr[i] = sc.nextInt();
temSum = temSum + arr[i];
}
for (int i = c; i < n; i++) {
if (temSum <= t) {
count++;
}
arr[i] = sc.nextInt();
temSum += arr[i];
temSum -= arr[i - c];
}
if (temSum <= t) {
count++;
}
System.out.println(count);
}
}
} #include <bits/stdc++.h>
using namespace std;
int main()
{ int n,t,c; int a[200010]; while(cin>>n>>t>>c) { int sum=0,count=0; for(int i=0;i<n;i++) cin>>a[i]; if(c > n) continue; for(int i=0;i<c;i++) sum += a[i]; if(sum <= t) count++; for(int i=c;i<n;i++) { sum -= a[i-c]; sum += a[i]; if(sum <= t) count++; } cout<<count<<endl; } return 0;
} #include<iostream>
#include<vector>
using namespace std;
int n, t, c;
//从k开始,连续往前找c个位置
int sum;
int cnt;
int flag;
int slider(int k, int c, vector<int> a) {
sum = 0;
cnt = 0;
while (cnt < c) {
sum = sum + a[k];
k--;
cnt++;
}
return sum;
}
int main() {
//freopen("Text.txt", "r", stdin);
while (cin >> n >> t >> c) {
vector<int> a(n + 1);
flag = 0;
for (int i = 1; i <= n; i++) {
cin >> a[i];
}
for (int i = n; i>=c; i--) {
if (slider(i, c, a) <= t) {
flag = 1;
cout << i - c + 1 << endl;
break;
}
}
if(flag != 1) cout << 0 << endl;
}
return 0;
}
一开始的思路是,
既然题目已经给出罪犯的罪行等级是按照从小到大来排列的,那么只需要从大到小找连续相邻的c个罪犯,如果满足其和小于等于t,即表示该序列符合题意,那么从该点开始向左,所有的组合就一定都满足。此时无需继续向左分片搜索,而可以直接得出分组数目为当前下标-c+1。
但是提示超时。
后来参考了评论区的“滑块”思想,如下所示:
#include<iostream>
#include<vector>
using namespace std;
int n, t, c;
int main() {
while (cin >> n >> t >> c) {
vector<int> a(n + 1);
int sum = 0;
int cnt = 0;
for (int i = 1; i <= n; i++) {
cin >> a[i];
if (i <= c) sum += a[i];
}
if(sum <= t) cnt++;
for (int i = 1; i <= n - c; i++) {
sum += a[i + c] - a[i];//滑块
if (sum <= t) cnt ++;
// else break;//此处不能break,为什么?
}
cout << cnt << endl;
}
return 0;
}
importjava.util.Scanner;publicclassMain{publicstaticvoidmain(String[] args){Scanner sc = newScanner(System.in);while(sc.hasNext()){intn = sc.nextInt();intt = sc.nextInt();intc = sc.nextInt();int[] time = newint[n];for(inti=0;i<n;i++){time[i] = sc.nextInt();}System.out.println(calNum(n, t, c, time));}}publicstaticintcalNum(intn, intt, intc, int[] time){if(n<c)return0;intnum = 0;intsum = 0;for(inti=0;i<c;i++){sum+=time[i];}if(sum<=t)num++;for(inti=c;i<n;i++){sum += time[i] - time[i-c];if(sum<=t)num++;}returnnum;}}