題目一:罪犯轉移
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
解析:考察數組的滑動窗口機制,否則會超時。
注:使用BufferedReader讀取數據的時候一定要Throws Exception
import java.util.*;
import java.io.*;
public class Main{
public static void main(String[] args)throws Exception{
BufferedReader br=new BufferedReader(new InputStreamReader(System.in));
String s="";
while((s=br.readLine())!=null)
{
String[] strs=s.split(" ");//0爲數組長度,1爲數組和上限,2爲子數組長度
int n=Integer.parseInt(strs[0]);
int t=Integer.parseInt(strs[1]);
int c=Integer.parseInt(strs[2]);
int[] data=new int[n];
s=br.readLine();
strs=s.split(" ");
for(int i=0;i<n;i++)
{
data[i]=Integer.parseInt(strs[i]);
}
int count=help(data,c,t);
System.out.println(""+count);
}
br.close();
}
//滑動窗口機制,否則會超時。
public static int help(int[] data,int c,int t)
{
int count=0;
int cursum=0;
for(int i=0;i<c;i++)
{
cursum+=data[i];
}
if(cursum <= t)
count++;
for(int i=c;i<data.length;i++)
{
cursum-=data[i-c];
cursum+=data[i];
if(cursum <= t)
count++;
}
return count;
}
}
題目二:裁剪網格紙
度度熊有一張網格紙,但是紙上有一些點過的點,每個點都在網格點上,若把網格看成一個座標軸平行於網格線的座標系的話,每個點可以用一對整數x,y來表示。度度熊必須沿着網格線畫一個正方形,使所有點在正方形的內部或者邊界。然後把這個正方形剪下來。問剪掉正方形的最小面積是多少。
輸入描述:
第一行一個數n(2≤n≤1000)表示點數,接下來每行一對整數xi,yi(-1e9<=xi,yi<=1e9)表示網格上的點
輸出描述:
一行輸出最小面積
輸入例子:
2
0 0
0 3
輸出例子:
9
解析:求出x,y座標最大距離中的較大者即可。本解法性能不好,其實只記錄就可以了,不用排序。
import java.util.*;
public class Main{
public static void main(String[] args){
Scanner in=new Scanner(System.in);
while(in.hasNext())
{
int rows=in.nextInt();
int[] left=new int[rows];
int[] right=new int[rows];
for(int i=0;i<rows;i++)
{
left[i]=in.nextInt();
right[i]=in.nextInt();
}
Arrays.sort(left);
Arrays.sort(right);
int max_left=left[rows-1]-left[0];
int max_right=right[rows-1]-right[0];
int max=Math.max(max_left,max_right);
System.out.println(""+max*max);
}
in.close();
}
}
題目三:釣魚比賽
ss請cc來家裏釣魚,魚塘可劃分爲n*m的格子,每個格子每分鐘有不同的概率釣上魚,cc一直在座標(x,y)的格子釣魚,而ss每分鐘隨機釣一個格子。問t分鐘後他們誰至少釣到一條魚的概率大?爲多少?
輸入描述:
第一行五個整數n,m,x,y,t(1≤n,m,t≤1000,1≤x≤n,1≤y≤m);
接下來爲一個n*m的矩陣,每行m個一位小數,共n行,第i行第j個數代表座標爲(i,j)的格子釣到魚的概率爲p(0≤p≤1)
輸出描述:
輸出兩行。第一行爲概率大的人的名字(cc/ss/equal),第二行爲這個概率(保留2位小數)
輸入例子:
2 2 1 1 1
0.2 0.1
0.1 0.4
輸出例子:
equal
0.20
注:1.BufferedReader讀取數據時要拋出異常。
2.保留兩位小數的輸出方法System.out.printf("%.2f\n",decimal);
import java.util.*;
import java.io.*;
public class Main{
public static void main(String[] args)throws Exception{
BufferedReader br=new BufferedReader(new InputStreamReader(System.in));
String s="";
while((s=br.readLine())!=null)
{
String[] strs=s.trim().split(" ");
int n=Integer.parseInt(strs[0]);
int m=Integer.parseInt(strs[1]);
int x=Integer.parseInt(strs[2]);
int y=Integer.parseInt(strs[3]);
int t=Integer.parseInt(strs[4]);
double[][] matrix=new double[n][m];
//記錄矩陣所有元素的和,爲ss做準備
double sum=0;
//矩陣賦值
for(int i=0;i<n;i++)
{
s=br.readLine();
strs=s.split(" ");
for(int j=0;j<m;j++)
{
matrix[i][j]=Double.parseDouble(strs[j]);
sum+=matrix[i][j];
}
}
//cc釣到魚的概率
double cc=1-Math.pow((1-matrix[x-1][y-1]),t);
//ss釣到魚的概率
double ss=1-Math.pow((1-(sum/(n*m))),t);
if(cc - ss > 0)//cc概率大
{
System.out.println("cc");
System.out.printf("%.2f\n", cc);
}
else if(ss - cc > 0)//ss概率大
{
System.out.println("ss");
System.out.printf("%.2f\n", ss);
}
else//一樣大
{
System.out.println("equal");
System.out.printf("%.2f\n", cc);
}
}
br.close();
}
}
題目四:蘑菇陣
現在有兩個好友A和B,住在一片長有蘑菇的由n*m個方格組成的草地,A在(1,1),B在(n,m)。現在A想要拜訪B,由於她只想去B的家,所以每次她只會走(i,j+1)或(i+1,j)這樣的路線,在草地上有k個蘑菇種在格子裏(多個蘑菇可能在同一方格),問:A如果每一步隨機選擇的話(若她在邊界上,則只有一種選擇),那麼她不碰到蘑菇走到B的家的概率是多少?
輸入描述:
第一行N,M,K(2 ≤ N,M ≤ 20, k ≤ 100),N,M爲草地大小,接下來K行,每行兩個整數x,y,代表(x,y)處有一個蘑菇。
輸出描述:
輸出一行,代表所求概率(保留到2位小數)
輸入例子:
2 2 1
2 1
輸出例子:
0.50
這道題就沒什麼好說的了,不能用可行的路數/總路數,反正繞的一比。
import java.util.*;
import java.io.*;
public class Main{
public static void main(String[] args)throws Exception{
BufferedReader br=new BufferedReader(new InputStreamReader(System.in));
String s="";
while((s=br.readLine())!=null){
String[] strs=s.split(" ");
int n=Integer.parseInt(strs[0]);
int m=Integer.parseInt(strs[1]);
int k=Integer.parseInt(strs[2]);
int[][] matrix=new int[n][m];
for(int i=0;i<k;i++)
{
s=br.readLine();
strs=s.split(" ");
int x=Integer.parseInt(strs[0])-1;
int y=Integer.parseInt(strs[1])-1;
matrix[x][y]++;
}
double d=help(matrix);
System.out.printf("%.2f\n",d);
}
br.close();
}
//可行的路數
public static double help(int[][] matrix)
{
if(matrix[0][0]!=0||matrix[matrix.length-1][matrix[0].length-1]!=0)
return 0;
int rows=matrix.length;
int cols=matrix[0].length;
double[][]dp=new double[rows][cols];//dp[i][j]表示matrix[i][j]的可達概率;
dp[0][0]=1;
//初始化
for(int j=1;j<cols;j++)
{
if(matrix[0][j]!=0)//若有蘑菇則爲0,;
dp[0][j]=0;
else if(rows!=1)//若有多行,在前一格有0.5的概率向下了,所以乘以0.5
dp[0][j]=0.5*dp[0][j-1];
else//若只有一行,則沒有抉擇,不用乘以0.5
dp[0][j]=dp[0][j-1];
}
for(int i=1;i<rows;i++)
{
if(matrix[i][0]!=0)
dp[i][0]=0;
else if(cols!=1)
dp[i][0]=0.5*dp[i-1][0];
else
dp[i][0]=dp[i-1][0];
}
//general
for(int i=1;i<rows;i++)
{
for(int j=1;j<cols;j++)
{
if(matrix[i][j]!=0)
dp[i][j]=0;
else if(i < rows-1&&j < cols-1)
dp[i][j]=0.5*dp[i-1][j]+0.5*dp[i][j-1];
else if(i == rows-1&&j < cols-1)
dp[i][j]=dp[i][j-1]+0.5*dp[i-1][j];
else if(j == cols-1&&i < rows-1)
dp[i][j]=dp[i-1][j]+0.5*dp[i][j-1];
else
dp[i][j]=dp[i-1][j]+dp[i][j-1];
}
}
return dp[rows-1][cols-1];
}
}