输入
H,W,X,K
int[H][W]
H代表行,W代表列,X代表要替换成的数字,k代表要替换多少行或者列(替换的行列数之和可以小于K).
输出:
各种替换可能中,数组的最大和。
例子:
输入:
8
8
29
14
-89 -76 92 61 5 -18 -68 90
-3 44 -9 84 -36 51 -43 85
11 -72 5 -90 -43 -94 5 97
-90 22 66 29 -26 66 -29 -38
82 -60 60 -9 -23 -8 -59 -13
-4 -68 -4 59 78 25 99 -86
-4 23 21 53 53 -25 -31 -66
38 50 -35 -98 -49 -33 -31 88
output:2100
输入:
3
4
3
2
1 -1 1 1
5 -5 5 5
9 -9 9 9
输出:
60
一开始的想法是直接贪心。每次替换最大增量的行或者列:
代码如下:
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.HashSet;
import java.util.Scanner;
import java.util.Set;
public class Main {
private int H;
private int W;
private int X;
private int K;
private int[][] arr;
private int sumR[];
private int sumC[];
public Main() {
Scanner sc = new Scanner(System.in);
H = sc.nextInt();
W = sc.nextInt();
X = sc.nextInt();
K = sc.nextInt();
sumR = new int[H];
sumC = new int[W];
arr = new int[H][W];
for(int i = 0; i<H; i++) {
for(int j = 0; j<W; j++) {
arr[i][j] = sc.nextInt();
sumR[i]+=arr[i][j];
}
}
for(int j = 0; j<W; j++) {
for(int i = 0; i<H; i++) {
sumC[j] +=arr[i][j];
}
}
}
public int getMin(int[] a) {
int min=0;
for(int i=1; i<a.length; i++) {
if(a[min]>a[i]) min = i;
}
return min;
}
public void solve() {
for(int temp = 0; temp<K&&temp<(W+H); temp++) {
int minSumR = getMin(sumR);
int minSumC = getMin(sumC);
if((W*X-sumR[minSumR])>=(H*X-sumC[minSumC])&&((W*X-sumR[minSumR])>0)) {
for(int j = 0; j<W; j++) {
sumC[j] = sumC[j]-arr[minSumR][j]+X;
arr[minSumR][j] = X;
}
sumR[minSumR] = W*X;
} else if((W*X-sumR[minSumR])<=(H*X-sumC[minSumC])&&((H*X-sumC[minSumC])>0)) {
for(int i=0; i<H; i++ ){
sumR[i] = sumR[i]-arr[i][minSumC]+X;
arr[i][minSumC] = X;
}
sumC[minSumC] = H*X;
}
}
int sum = 0;
for(int i= 0; i<H; i++) {
sum+=sumR[i];
}
for(int i = 0; i<H; i++) {
for(int j = 0; j<W; j++) {
System.out.print(arr[i][j]+" ");
}
System.out.println();
}
System.out.println(sum);
}
public static void main(String[] args) {
Main m = new Main();
m.solve();
}
}
跑出来,第一个例子不对。死活找不到原因。
大神给举例:
3
2
3
2
-100 -100
-1 -1
-1 -1
按照我的想法,跑出来是10
但是实际上可以有
3 3
3 3
3 3
输出是18。
修改后代码如下:
package Indeed;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Scanner;
public class Third {
private int[] arr = {0,1,2,3,4,5,6,7,8,9};
private int k;
private int col;
private int[][] nums;
private int[] sumC;
private int x;
private int max;
private int changeNums;
public Third(int H, int W,int X,int changeNums,int[][] nums) {
this.k = H;
this.col = W;
this.nums = nums;
this.x = X;
this.changeNums = changeNums;
sumC = new int[col];
for(int j = 0; j<col; j++) sumC[j] = 0;
}
public int solve() {
int max = Integer.MIN_VALUE;
for(int i = 0; i<(1<<k); i++) {
int n=0;
for (int j=0;j<k;j++)
if(((i>>j)&1)==1)
n++;
int length =changeNums-n;
if(length<0) continue;
int[][] numsAfter = nums;
for (int j=0;j<k;j++)
if(((i>>j)&1)==1)
for ( int l = 0 ; l < col ; l ++ )
numsAfter[j][l] = x ;
for(int j = 0; j<col;j++) {
sumC[j] = 0;
for(int t = 0; t<k; t++) {
sumC[j]+=numsAfter[t][j];
}
}
sort(sumC);
for(int t = 0; t<col&&t<length&&sumC[t]<k*x;t++) {
sumC[t] = k*x;
}
int result = 0;
for(int t = 0; t<col; t++) {
result+=sumC[t];
}
if(i==120) {
for(int row = 0; row<k; row++) {
for(int j = 0;j<col; j++) {
System.out.print(numsAfter[row][j]+" ");
}
System.out.println();
}
System.out.println(result+" max:"+max);
}
max = Math.max(max, result);
}
return max;
}
public void sort(int[] a) {
for(int i = 0; i<a.length; i++) {
for(int j = i; j<a.length; j++) {
if(a[i]>a[j]) {
int temp = a[j];
a[j] = a[i];
a[i] = temp;
}
}
}
}
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
int H = sc.nextInt();
int W = sc.nextInt();
int x = sc.nextInt();
int k = sc.nextInt();
int[][] nums = new int[H][W];
for(int i = 0; i<H; i++) {
for(int j = 0; j<W; j++) {
nums[i][j] = sc.nextInt();
}
}
Third th = new Third(H,W,x,k,nums);
System.out.println(th.solve());
}
}
嗯。还是错了。大神帮忙找原因。
原因找到。
主要有两个原因。
1、int[] a = new int[2][3];
int[] b = a;
b[1] =2;
a的大小也会随着b的大小的改变而改变,
因此 代码里的 numsAfter = nums 应该改成每一个数字进行赋值。
2、sort排序。
sort是对整个sumC数组进行的排序。但是实际上 sumC数组里面只有前col个有数据,剩余部分的数据都是之前的数据未清除。所以应是对前col个数据进行排序。然后同样只计算前col个数据的和。
修改后的代码如下:
package Indeed;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Scanner;
public class Third {
private int[] arr = {0,1,2,3,4,5,6,7,8,9};
private int k;
private int col;
private static int[][] nums = new int[10][200];
private int[] sumC = new int[200];
private int x;
private int max;
private int changeNums;
public Third() {
Scanner sc = new Scanner(System.in);
k = sc.nextInt();
col = sc.nextInt();
x = sc.nextInt();
changeNums = sc.nextInt();
for(int i = 0; i<k; i++) {
for(int j = 0; j<col; j++) {
nums[i][j] = sc.nextInt();
}
}
}
public int solve() {
int max = Integer.MIN_VALUE;
for(int i = 0; i<(1<<k); i++) {
int n=0;
for (int j=0;j<k;j++)
if(((i>>j)&1)==1)
n++;
int length =changeNums-n;
if(length<0) continue;
int[][] numsAfter = new int[k][col];
for(int l = 0; l<k; l++) {
for(int t = 0; t<col; t++) {
numsAfter[l][t] = nums[l][t];
}
}
for (int j=0;j<k;j++)
if(((i>>j)&1)==1)
for ( int l = 0 ; l < col ; l ++ )
numsAfter[j][l] = x ;
for(int j = 0; j<col;j++) {
sumC[j] = 0;
for(int t = 0; t<k; t++) {
sumC[j]+=numsAfter[t][j];
}
}
sort(sumC,0,col);
for(int t = 0; t<col&&t<length&&sumC[t]<k*x;t++) {
sumC[t] = k*x;
}
int result = 0;
for(int t = 0; t<col; t++) {
result+=sumC[t];
}
max = Math.max(max, result);
}
return max;
}
public void sort(int[] a,int start, int end) {
for(int i = start; i<end; i++) {
for(int j = i; j<end; j++) {
if(a[i]>a[j]) {
int temp = a[j];
a[j] = a[i];
a[i] = temp;
}
}
}
}
public static void main(String[] args) {
Third th = new Third();
System.out.println(th.solve());
}
}
整理了下代码:
package Indeed;
/*
*
8
8
29
14
-89 -76 92 61 5 -18 -68 90
-3 44 -9 84 -36 51 -43 85
11 -72 5 -90 -43 -94 5 97
-90 22 66 29 -26 66 -29 -38
82 -60 60 -9 -23 -8 -59 -13
-4 -68 -4 59 78 25 99 -86
-4 23 21 53 53 -25 -31 -66
38 50 -35 -98 -49 -33 -31 88
output:2100
3
2
3
2
-100 -100
-1 -1
-1 -1
output:18
*/
import java.util.Scanner;
public class Main {
private int H;
private int W;
private int X;
private int K;
private int[][] arr = new int[10][200];
private int[][] arrAfter = new int[10][200];
public Main() {
Scanner sc = new Scanner(System.in);
H = sc.nextInt();
W = sc.nextInt();
X = sc.nextInt();
K = sc.nextInt();
arr = new int[H][W];
for(int i = 0; i<H; i++) {
for(int j = 0; j<W; j++) {
arr[i][j] = sc.nextInt();
}
}
}
public int solve() {
int max = Integer.MIN_VALUE;
for(int s = 0; s<(1<<H);s++) {
int n = 0;
int[][] nums = new int[H][W];
for(int i = 0; i<H; i++) {
for(int j = 0; j<W; j++) {
nums[i][j] = arr[i][j];
}
}
for(int j = 0; j<H; j++) {
if(((s>>j)&1)==1) {
for(int l = 0; l<W; l++) {
nums[j][l] = X;
}
n++;
}
}
int size = K-n;
int[] colSum = new int [W];
for(int j = 0; j<W; j++) {
colSum[j] = 0;
for(int i = 0; i<H; i++) {
colSum[j]+=nums[i][j];
}
}
sort(colSum,0,W);
for(int i = 0; i<size&&i<W&&colSum[i]<H*X; i++) {
colSum[i]=H*X;
}
int result = 0;
for(int i = 0; i<W; i++) {
result+=colSum[i];
}
max = Math.max(result, max);
}
return max;
}
public void sort(int[] colSum, int start, int end) {
for(int i = start; i<end; i++) {
for(int j = i; j<end; j++) {
if(colSum[i]>colSum[j]) {
int temp = colSum[i];
colSum[i] = colSum[j];
colSum[j] = temp;
}
}
}
}
public static void main(String[] args) {
Main m = new Main();
System.out.println(m.solve());
}
}