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
import java.util.*;
public class Main{
public static void main(String[] args){
Scanner in = new Scanner(System.in);
while(in.hasNext()){ //处理多组数据
int count = 0;
int n = in.nextInt(),t = in.nextInt(),c = in.nextInt();
int[]crime = new int[n];
int[] dp = new int[n];//保留求和值
for(int i = 0;i<n;i++)
{
crime[i] = in.nextInt();
if(i == 0) //边界值
{
dp[i] = crime[i];
}
else if(i<=(c-1))
{
dp[i] = dp[i-1]+crime[i];
}
else
{
dp[i] = dp[i-1]+crime[i]-crime[i-c];
}
if(i>=(c-1) && dp[i]<=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);
}
}
} import java.util.Scanner;
public class Main {
public static void main(String[] args) {
Scanner in = new Scanner(System.in);
while(in.hasNext()){
int n = in.nextInt();
int t = in.nextInt();
int c = in.nextInt();
int[] weights = new int[n];
int i = -1;
while(++i<n && in.hasNext()){
weights[i] = in.nextInt();
}
int way = 0, sum = 0;
for(int j=0; j<c; j++){
sum += weights[j];
}
if (sum<=t) {
way++;
}
for(int j=1; j<=n-c; j++){
sum += weights[j+c-1] - weights[j-1];
if (sum<=t) {
way++;
}
}
System.out.println(way);
}
}
}
此题主要是抓住 转移入狱时间连续的罪犯 这一条件,那么我们在累加可能的转移方式时候,只要满足不超过罪行总值,就可以把罪犯往后挪一位(当然为了保证人数不变,前面第一个罪犯就得去除),以此来计算满足条件的所有可能情况。
import java.util.*;
public class Main{
public static void main(String[] args){
Scanner in = new Scanner(System.in);
int n,t,c;
int criminal[];
while(in.hasNext()){
n = in.nextInt();
t = in.nextInt();
c = in.nextInt();
criminal = new int[n];
for (int i = 0; i < n; i++){
criminal[i] = in.nextInt();
}
int count = 0;
int sum = 0;
for (int i = 0; i < c; i++){
sum += criminal[i];
}
for (int i = 0; i <= n - c; i++){
if (t >= sum){
count++;
}
if (i == n - c) break;
sum -= criminal[i];
sum += criminal[i + c];
}
System.out.println(count);
}
}
}
//先计算前n项罪犯的罪行和sum[n+1],当需要求某一连续区间[i,j]的总和时,只需要用sum[j] - sum[i]即可。
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[] weight = new int[n];
for (int i = 0; i < n; i++) {
weight[i] = sc.nextInt();
}
calWeight(n, t, c, weight);
}
}
private static void calWeight(int n,int t,int c,int[] weight){
int count = 0;
//先计算前n项和的数组
int [] sumN = new int[n + 1];
sumN[0] = 0;
for(int i = 1;i<=n;i++){
sumN[i] = sumN[i - 1] + weight[i - 1];
}
for(int j = c;j<=n;j++){
if(sumN[j] - sumN[j - c] <= t){
count++;
}
}
System.out.println(count);
}
}
import java.util.Scanner;
/**
* 数组平移的思想真的很好
*
*/
public class Main {
public static void main(String[] args) {
Scanner in = new Scanner(System.in);
while (in.hasNext()) {
int n = in.nextInt();
int t = in.nextInt();// 总和
int c = in.nextInt();
int p = 0;
int[] a = new int[n];
while (p < n) {
a[p] = in.nextInt();
++p;
}
int result = 0;
int sum = 0;
for (int i = 0; i < c; i++) {
sum += a[i];
}
if(sum<t){
result++;
}
for (int j = c; j < n; j++) {
sum += a[j] - a[j - c];//数组平移的思想
if (sum <=t) {
result++;
}
}
System.out.println(result);
}
}
}
import java.util.Scanner;
public class Main{
//普通的思路就不多说了,时间复杂度肯定高,不能在规定时间内完成,
//我说一个我个人的O(n)的算法,只需要一次从左到右就可以计算出结果
//首先找一行数 1 2 3 4 5 6 7 8 9,
//这串数字总长9,假设最大和为20,找连续四个数的和,且不超过20
//这里我们需要两个指针,首先第一个指针指向数字1,让他从左到右一次累加前四个数
//也就是第一个指针指向了数字4;
//然后判断这个数是否小于20,如果小于20,结果集加1;
//然后第一个指针继续往下走一步,指向数字5,并且加上当前的数字,
//这时候就需要用第二个指针了,第二个指针指向数字1
//然后我们用当前的和减去第一个指针指向的数字1,
//然后判断和的大小,以此类推,第一个指针走一步,
//同时第二个指针也跟着走一步,一直保持第一个指针和第二个指针的间隔为
//需要累加的数字个数减1,累加的终止条件就是第一个指针走到末尾。
//以上就是算法的思路,下面看代码
public int criminal(int[] people ,int max , int limit){
//people是数组,max表示罪行值,limit表示连续的c名犯人。
//i表示第一个指针 ,count用来存储累加的和,
//result记录最后有多少种方法,temp记录limit的值
int i = 0 ,count = 0 , j = 0 , result = 0 , temp = limit;
//终止条件:i走到末尾
while(i<people.length){
//i从0开始。如果i小于转移犯人数,依次累计罪行值
while(i<temp){
count+=people[i];
i++;
}
if(limit-i==0){
//如果i是从0开始计算的,不减数
}else{
//否则,如果i已经累加完成过一次。count需要减去之前的开始罪行值
//因为每次只减去一个,所以第二个指针需要下移一位。
count = count - people[j];
j++;
}
//判断count的值是否小于等于最大罪行值,如果满足,结果集加1
if(count<=max){
result++;
}
//temp+1,之所以temp需要加1是因为,每次i在往后移动,
//如果temp的值保持不变,就只能累加一次,陷入死循环,
//所以必须保证i每次能够前进一步。所以temp需要同时+1;
//但是不用考虑temp的终止条件,她的值肯定最后是等于数组长度的。
temp++;
}
return result;
}
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
do{
int len = sc.nextInt() ;
int max = sc.nextInt();
int limit = sc.nextInt();
int[] people =new int[len];
for(int i = 0 ; i < len ; i++){
people[i] = sc.nextInt();
}
int index = criminal(people,max,limit);
System.out.println(index);
}while(sc.hasNext());
}
}
public static void main(String[] args){
Scanner sc = new Scanner(System.in);
while(sc.hasNext()){
String[] temp1 = sc.nextLine().split(" ");
int n =Integer.parseInt(temp1[0]);
int t =Integer.parseInt(temp1[1]);
int c =Integer.parseInt(temp1[2]);
int[] nums = new int[n];
String[] temp2 = sc.nextLine().split(" ");
for(int i = 0 ; i < n ; i ++){
nums[i] = Integer.parseInt(temp2[i]);
}
int start = 0,ret = 0;
int[] dp = new int[n];
dp[0] = nums[0];
for(int i = 1 ; i < n ; i ++){
dp[i] += dp[i-1]+ nums[i];
//large than t
while(dp[i] > t ){
dp[i] -= nums[start ++];
}
if(i - start + 1 == c){
ret ++;
dp[i] -= nums[start ++];
}
}
System.out.println(ret);
}//while
}//main