打包
题目链接:http://lx.lanqiao.cn/problem.page?gpid=T2978
这个是一道二分的题目,题目需要求的最大重量肯定是介于[单件物品最大重量,所有物品总质量之间的],这个肯定是没有问题的,然后我们就需要在这个区间中二分查找满足条件的答案即可,对于
check
函数我们只需要检查在每个包裹的最大重量不超过传入的targetWeight
时能打包几个包裹就行,当可以打包的包裹数小于等于需要的包裹数时,说明这个重量是可以满足的,就可以去查找更小的质量是不是也满足为什么
当可以打包的包裹数小于等于需要的包裹数时,说明这个重量是可以满足的
?因为当你使用更少的包裹就可以完成这个重量要求的时候,随便从一个包裹里面拿几件出来拼成另一个包裹也是可以满足的,也就是说包裹可以用的比要求的少,但是不能更多
package daily;
import java.util.Scanner;
/**
* http://lx.lanqiao.cn/problem.page?gpid=T2978
*
* @author Jia
*
*/
public class day3_30_1 {
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
int N = sc.nextInt();
int M = sc.nextInt();
int[] weights = new int[N];
int maxWeight = 0;// 所有物品的最大重量
int sumWeight = 0;// 所有物品的总重量
for (int i = 0; i < weights.length; i++) {
weights[i] = sc.nextInt();
maxWeight = Math.max(maxWeight, weights[i]);
sumWeight += weights[i];
}
sc.close();
// 二分寻找满足条件的最小重量
int left = maxWeight;
int right = sumWeight;
while (left <= right) {
int mid = (right - left) / 2 + left;
if (check(weights, mid, M)) {
// 当这个重量可以满足的时候继续往左边查找
right = mid - 1;
} else {
// 这个重量不能拼出来的时候向右边查找
left = mid + 1;
}
}
System.out.println(left);
}
/**
* 判断当前是否可以满足打包成packNum个包裹,且每个质量均不超过`targetWeight`
*
* @param weights
* @param targetWeight
* @param packNum
* @return 如果可以则返回true,否则返回false
*/
private static boolean check(int[] weights, int targetWeight, int packNum) {
int curWeight = 0;
int curPackNum = 0;
for (int i = 0; i < weights.length; i++) {
if (curWeight + weights[i] > targetWeight) {
curPackNum++;
curWeight = 0;
}
curWeight += weights[i];
}
curPackNum++;
return curPackNum <= packNum;
}
}
约数个数
题目链接:http://lx.lanqiao.cn/problem.page?gpid=T2606
这个想不到好的方法就直接暴力上了,看到了数据规模,估摸着应该能过一半把,然后最后拿了60%,还挺不错
方法类似于筛选素数的方法,从小向大遍历,遍历到一个数直接给它的因数加一,同时给ans加上当前数因数的数目并取余直到结束
其实还想用打表做来着,直接把10000000个数据直接放数组中然后提交了,但是输出的时候卡了好久出不来,就放弃了(或许也可以直接输出到文件中,看他的内存限制是512MB,10^7个int数字也就大概占用50MB吧,感觉方法还是可行的hhh)
package daily;
import java.util.Arrays;
import java.util.Scanner;
/**
* http://lx.lanqiao.cn/problem.page?gpid=T2606
*
* @author Jia
*
*/
public class day3_30_2 {
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
int n = sc.nextInt();
sc.close();
int[] arr = new int[n + 1];
int ans = 1;
int[] ansArr = new int[n + 1];
Arrays.fill(arr, 1);// 使用1填充数组
// 统计约数的数量
for (int i = 2; i < arr.length; i++) {
int j = i;
while (j < arr.length) {
arr[j] = (arr[j] + 1) % (1000000007);
j += i;
}
ans = (ans + arr[i]) % (1000000007);
ansArr[i] = ans;
}
System.out.println(ans);
}
}
寻找三位数
题目链接:http://lx.lanqiao.cn/problem.page?gpid=T2038
这个题常规题,直接dfs获得所有的排列数,然后判断每种排列是不是满足条件就OK了
建议把这个题直接当获取排列数的模板记下,其他题中只需要更改
check
函数中的内容就行了
package daily;
/**
* http://lx.lanqiao.cn/problem.page?gpid=T2038
*
* @author Jia
*
*/
public class day3_31_3 {
static int[] arr = { 1, 2, 3, 4, 5, 6, 7, 8, 9 };
public static void main(String[] args) {
dfs(0);// 深度有限遍历所有排列数
}
/**
* dfs获得所有排列数
*
* @param index
*/
private static void dfs(int index) {
if (index == arr.length) {
check();
} else {
for (int i = index; i < arr.length; i++) {
swap(i, index);
dfs(index + 1);
swap(i, index);
}
}
}
/**
* 检查当前排列是否满足条件
*/
private static void check() {
int num1 = getVal(0, 3);
int num2 = getVal(3, 6);
int num3 = getVal(6, 9);
if (num1 * 2 == num2 && num1 * 3 == num3) {
System.out.println(num1 + " " + num2 + " " + num3);
}
};
/**
* 将arr在区间[begin,end)中的值转换为int返回
*
* @param begin
* @param end
* @return
*/
private static int getVal(int begin, int end) {
int ret = 0;
for (int i = begin; i < end; i++) {
ret = ret * 10 + arr[i];
}
return ret;
}
/**
* 交换数组两个位置的元素
*
* @param i
* @param j
*/
private static void swap(int i, int j) {
int temp = arr[i];
arr[i] = arr[j];
arr[j] = temp;
}
}
第二点五个不高兴的小明
题目链接:http://lx.lanqiao.cn/problem.page?gpid=T770
这个题应该是动态规划做的,不过限制比较难的就是要求必须要经过t次到达终点,和常规的上台阶相比难了一点点
还是一样的,定义dp数组,有t+1行,n+2列,其中 d p [ i ] [ j ] dp[i][j] dp[i][j]表示第 i i i步到达第 j j j个格子时的最大权重
因此,递归方程可以写出来为:
d p [ i ] [ j ] = m a x ( d p [ i ] [ j ] , d p [ i − 1 ] [ j − m ] + w e i g h t [ j − 1 ] ) , ( 其 中 m ∈ [ 1 , p ] ) dp[i][j]=max(dp[i][j], dp[i-1][j-m]+weight[j-1]),(其中m\in[1,p]) dp[i][j]=max(dp[i][j],dp[i−1][j−m]+weight[j−1]),(其中m∈[1,p])
然后需要将数组的所有元素都先初始化为Intger.MIN_VALUE
,这样可以保证权重比0小时发生更新的错误,然后第一步的值也需要预先更新好