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;}}