s+w排序是最优解:(反证法)
找到严格逆序的一对相邻层 : w[i-1] + s[i-1] > w[i]+s[i] ;
交换 i和i-1 危险值risk变成 :
i-1 层: w[0]+w[1]..+w[i-2]-s[i-1] ---> w[0]+w[1]..+w[i-2]-s[i]
i 层: w[0]+w[1]..+w[i-2]+w[i-1]-s[i] ---> w[0]+w[1]..+w[i-2]+w[i]-s[i-1]
两项都除去w[0]+..+w[i-2]------------------------------------------------
i-1 层 : -s[i-1] --------> -s[i]
i 层 : w[i-1]-s[i] -------> w[i]-s[i-1];
然后两边加上 s[i]+s[i-1] -----------------------------------------------
i-1 层 : s[i] --------> s[i-1]
i 层 : w[i-1]+s[i-1] -------> w[i]+s[i];
根据 w[i-1] + s[i-1] > w[i]+s[i] 且 w[i]>=1
得出结论:交换后的 w[i]+s[i] 或 s[i-1] 严格小于交换前的w[i-1]+s[i-1] ,所以在交换后的两个值都比交换前的一个值小,于是交换后的最大值不会变大,
假设 w[i-1] + s[i-1] 是最大值,那么交换后两个值都小于最大值,所以交换后最大值变小
假设 w[i-1] + s[i-1] 不是最大值,所以s[i]>=w[i-1]+s[i-1] ,所以交换后两项的最大值变得比w[i-1]+s[i-1]还小
综合上述结论,交换逆序后对其他层影响,所以最优解不是递增的话,那我们可以找到比最优解最大值还小的解(那么久悖论了);所以s+w单调递增就是最优解
import java.util.*;
public class Main{
public static void main(String[] args){
Scanner sc=new Scanner(System.in);
int n=sc.nextInt();
int[][] a=new int[n][2];
for(int i=0;i<n;i++){
int w=sc.nextInt();
int s=sc.nextInt();
a[i][0]=s+w;
a[i][1]=s;
}
Arrays.sort(a,(o1,o2)->{
return o1[0]-o2[0];
}); //s+w排序后就是最优解方案
int res=Integer.MIN_VALUE; //风险值会出现负数
int risk=0; //第一层风险值是0-s[0]
for(int i=0;i<n;i++){
int w=a[i][0]-a[i][1],s=a[i][1]; //改成w和s
res=Math.max(res,risk-s); //找最大风险值
risk+=w; //更新下一层风险值
}
System.out.println(res);
}
}
二刷的理解:
我们观察w和s,因为我们求最大值最小,那么不难发现应该是越往后Sw就越大,那么最大值大概率应该在后面,而且我们发现s越大那么越应该放在下面更好,因为越往下w的总和越大,此时s越大,Sw-s的值就会越小,我们还发现w也应该越大越放下面,因为w当第一层会被后面n层计算到,而放最后一层不会被计算
那么反过来,然后我们就发现了第一层w和s都是越小越好,最后一层w和s都是越大越好,所以我们按照w+s排序来决定顺序
import java.util.*;
public class Main{
public static void main(String[] args){
Scanner sc = new Scanner(System.in);
int n = sc.nextInt();
Pair p[] = new Pair[n];
for(int i = 0; i < n; i ++){
int w = sc.nextInt();
int s = sc.nextInt();
p[i] = new Pair(w, s);
}
Arrays.sort(p, 0, n);
long res = Long.MIN_VALUE, sum = 0;
for(int i = 0; i < n; i ++){
res = Math.max(sum - p[i].s, res);
sum += p[i].w;
}
System.out.println(res);
}
static class Pair implements Comparable<Pair>{
int w, s;
Pair(int w, int s){
this.w = w;
this.s = s;
}
public int compareTo(Pair o){
return (this.w + this.s) - (o.w + o.s);
}
}
}