一种双核CPU的两个核能够同时的处理任务,现在有n个已知数据量的任务需要交给CPU处理,假设已知CPU的每个核1秒可以处理1kb,每个核同时只能处理一项任务。n个任务可以按照任意顺序放入CPU进行处理,现在需要设计一个方案让CPU处理完这批任务所需的时间最少,求这个最小的时间。
输入描述:
输入包括两行: 第一行为整数n(1 ≤ n ≤ 50) 第二行为n个整数length[i](1024 ≤ length[i] ≤ 4194304),表示每个任务的长度为length[i]kb,每个数均为1024的倍数。
输出描述:
输出一个整数,表示最少需要处理的时间
输入例子:
5 3072 3072 7168 3072 1024
输出例子:
9216
思路:等价于求最接近总和一半的数,也就等价于一个容量为总和一半的背包问题
public class Main {
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
while(sc.hasNext()) {
int n = sc.nextInt();
int[]a=new int[n];
for(int i=0; i<n; i++)a[i]=sc.nextInt()/1024;
int sum=0;
for(int i:a)sum+=i;
int target = sum/2;
// pack algorithm
int[][] dp = new int[n+1][target+1];
for(int i=1; i<=n; i++)
for(int j=1; j<=target; j++)
if(j >= a[i-1])
dp[i][j] = Math.max(dp[i-1][j], dp[i-1][j-a[i-1]]+a[i-1]);
else
dp[i][j] = dp[i-1][j];
System.out.println((sum-dp[n][target])*1024);
}
}
}
小易拥有一个拥有魔力的手环上面有n个数字(构成一个环),当这个魔力手环每次使用魔力的时候就会发生一种奇特的变化:每个数字会变成自己跟后面一个数字的和(最后一个数字的后面一个数字是第一个),一旦某个位置的数字大于等于100就马上对100取模(比如某个位置变为103,就会自动变为3).现在给出这个魔力手环的构成,请你计算出使用k次魔力之后魔力手环的状态。
输入描述:
输入数据包括两行: 第一行为两个整数n(2 ≤ n ≤ 50)和k(1 ≤ k ≤ 2000000000),以空格分隔 第二行为魔力手环初始的n个数,以空格分隔。范围都在0至99.
输出描述:
输出魔力手环使用k次之后的状态,以空格分隔,行末无空格。
输入例子:
3 2 1 2 3
输出例子:
8 9 7思路:矩阵快速幂
http://huang22.top/2016/04/11/%E7%9F%A9%E9%98%B5%E5%BF%AB%E9%80%9F%E5%B9%82/
public class Main {
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
while(sc.hasNext()) {
int n = sc.nextInt(), m = sc.nextInt();
int[]a=new int[n];
for(int i=0; i<n; i++)a[i]=sc.nextInt();
int[][] matrix = new int[n][n];
for(int i=0; i<n; i++) {
matrix[i][i]=1;
matrix[(i+1)%n][i]=1;
}
int[][] pow = matrixPower(matrix, m);
int[] rst = helper(a, pow);
for(int i=0; i<rst.length-1; i++)
System.out.print(rst[i]+" ");
System.out.println(rst[n-1]);
}
}
public static int[][] matrixPower(int[][] a, int n) {
// 注意:初始化为单位矩阵
int[][] b = new int[a.length][a.length];
for(int i=0; i<a.length; i++)
b[i][i] = 1;
while(n != 0) {
if((n & 1) != 0)
b = helper(b, a);
n = n >> 1;
a = helper(a, a);
}
return b;
}
public static int[][] helper(int[][] a, int[][] b) {
// 写的是方阵相乘的结果
int[][] c = new int[a.length][a.length];
for(int i=0; i<a.length; i++)
for(int j=0; j<a.length; j++) {
for(int k=0; k<a.length; k++)
c[i][j] += a[i][k] * b[k][j];
c[i][j] %= 100;
}
return c;
}
public static int[] helper(int[] a, int[][] b) {
int[] c = new int[a.length];
for(int i=0; i<a.length; i++) {
for(int k=0; k<a.length; k++)
c[i] += a[k] * b[k][i];
c[i] %= 100;
}
return c;
}
}
小易有n块砖块,每一块砖块有一个高度。小易希望利用这些砖块堆砌两座相同高度的塔。为了让问题简单,砖块堆砌就是简单的高度相加,某一块砖只能使用在一座塔中一次。小易现在让能够堆砌出来的两座塔的高度尽量高,小易能否完成呢。
输入描述:
输入包括两行: 第一行为整数n(1 ≤ n ≤ 50),即一共有n块砖块 第二行为n个整数,表示每一块砖块的高度height[i] (1 ≤ height[i] ≤ 500000)
输出描述:
如果小易能堆砌出两座高度相同的塔,输出最高能拼凑的高度,如果不能则输出-1. 保证答案不大于500000。
输入例子:
3 2 3 5
输出例子:
5
思路:这道题真是惭愧,看了好几天别人的DP代码还是看不懂,后来用Java写DFS+剪枝,虽然想出了很多稀奇古怪的剪枝策略,但是无奈Java太慢了,只能AC 90%,可见DFS这种方法用来做这样的题还是很勉强
DP以后看懂了再更新吧。。。。
package l10;
import java.util.*;
/*
* DFS + 剪枝
* 但是Java是不行的
*/
public class Copy_4_of_Main {
static int rst = 0;
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
while(sc.hasNext()) {
int n = sc.nextInt();
int[]cost = new int[1+n];
for(int i=1; i<=n; i++)
cost[i]=sc.nextInt();
Arrays.sort(cost);
int[] tmp = new int[1+n];
for(int i=1; i<=n; i++)
tmp[i] = cost[n-i+1];
cost = tmp;
int[] rightSum = new int[1+n];
rightSum[n] = cost[n];
for(int i=n-1; i>=1; i--)
rightSum[i] = rightSum[i+1] + cost[i];
rst = 0;
dfs(cost, rightSum, 1, 0, 0);
System.out.println(rst == 0 ? -1 : rst);
}
}
private static void dfs(int[] cost, int[] rightSum, int cnt, int left, int right) {
if(left == right) rst = Math.max(rst, left);
if(cnt == cost.length) return;
if((left + right + rightSum[cnt]) / 2 <= rst) return;
if(left + rightSum[cnt] < right || right + rightSum[cnt] < left) return;
dfs(cost, rightSum, 1+cnt, left+cost[cnt], right);
dfs(cost, rightSum, 1+cnt, left, right+cost[cnt]);
dfs(cost, rightSum, 1+cnt, left, right);
}
}
易老师购买了一盒饼干,盒子中一共有k块饼干,但是数字k有些数位变得模糊了,看不清楚数字具体是多少了。易老师需要你帮忙把这k块饼干平分给n个小朋友,易老师保证这盒饼干能平分给n个小朋友。现在你需要计算出k有多少种可能的数值
输入描述:
输入包括两行: 第一行为盒子上的数值k,模糊的数位用X表示,长度小于18(可能有多个模糊的数位) 第二行为小朋友的人数n
输出描述:
输出k可能的数值种数,保证至少为1
输入例子:
9999999999999X 3
输出例子:
4
思路:DFS会TLE,因为后面的结果也前面是相关联的:到当前位为止的余数与前一位的余数个数是由关系的
就是把前面计算过的结果用起来
package l11;
import java.util.*;
/*
* 到当前位为止的余数与前一位的余数个数是由关系的
* 所以考虑用DP
*/
public class Main {
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
while(sc.hasNext()) {
String s = sc.next();
String sr = new StringBuilder(s).reverse().toString();
int n = sc.nextInt();
//dp[i][j]表示到index为i的时候,余数为j的个数
long[][] dp = new long[sr.length()+1][n];
dp[0][0] = 1;
int base = 1;
for(int i=1; i<=sr.length(); i++) {
if('X' == sr.charAt(i-1)) {
for(int j=0; j<10; j++) {
for(int k=0; k<n; k++) {
int newLeft = (k + j * base) % n;
dp[i][newLeft] += dp[i-1][k];
}
}
} else {
int j = sr.charAt(i-1) - '0';
for(int k=0; k<n; k++) {
int newLeft = (k + j * base) % n;
dp[i][newLeft] += dp[i-1][k];
}
}
base *= 10;
base %= n;
}
System.out.println(dp[sr.length()][0]);
}
}
}