problem1 link
$g[i]$表示解决前$i$个的代价,那么$g[i]$是所有$g[j]+cost(j+1,i)$的最小值。
import java.util.*; import java.math.*; import static java.lang.Math.*; public class FenceRepairing { public double calculateCost(String[] boards) { StringBuilder builder=new StringBuilder(); for(int i=0;i<boards.length;++i) { builder.append(boards[i]); } final String s=builder.toString(); final int n=s.length(); int[] f=new int[n+1]; f[0]=0; for(int i=1;i<=n;++i) { f[i]=f[i-1]; if(s.charAt(i-1)=='X') { ++f[i]; } } double[] g=new double[n+1]; g[0]=0; for(int i=1;i<=n;++i) { g[i]=g[i-1]; if(f[i]-f[i-1]!=0) { g[i]+=1; } for(int j=0;j<i;++j) { double t=g[j]; if(f[i]-f[j]>0) { t+=Math.sqrt(i-j); } if(t<g[i]) { g[i]=t; } } } return g[n]; } }
problem2 link
分别讨论$X$的取值区间即可。
import java.util.*; import java.math.*; import static java.lang.Math.*; public class ModularInequality { public int countSolutions(int[] A, int P) { Arrays.sort(A); int result=0; final int n=A.length; long sum=0; for(int x:A) { sum+=x; } if(sum>=P) { long k=(sum-P+n-1)/n; if(k<A[0]) { result+=A[0]-k; } } else { long k=(sum-P)/n; if(k<A[0]) { result+=A[0]-k; } } if(P+sum>=0) { long k=(P+sum)/n; if(A[n-1]<=k) { result+=k-A[n-1]+1; } } else { long k=(P+sum-(n-1))/n; if(A[n-1]<=k) { result+=k-A[n-1]+1; } } long pre=0; for(int i=1;i<n;++i) { pre+=A[i-1]; sum-=A[i-1]; if(A[i]==A[i-1]) { continue; } long aa=P-(sum-pre); long bb=i+i-n; if(bb==0) { if(aa>=0) { result+=A[i]-A[i-1]; } } else if(bb<0) { long k=-1; if(aa<0) { k=aa/bb; if(aa%bb!=0) { ++k; } } else if(aa==0) { k=0; } else { k=aa/bb; } if(k<A[i]) { result+=A[i]-Math.max(A[i-1],k); } } else { long k=-1; if(aa<0) { k=aa/bb; if(aa%bb!=0) { --k; } } else if(aa==0) { k=0; } else { k=aa/bb; } if(A[i-1]<=k) { result+=Math.min(k,A[i]-1)-A[i-1]+1; } } } return result; } }
problem3 link
从小到大依次枚举每个币种的面值。假设要求的答案为$f(n,K)$。当枚举第二种面值的时候,假设是2,那么后面所有的面值都是2的倍数,所以此时$f(n,K)=n$%$2+f(\frac{n}{2},K-1)$。
import java.util.*; import java.math.*; import static java.lang.Math.*; public class NewMoneySystem { public long chooseBanknotes(String N,int K) { map=new HashMap<>(); return dfs(Long.valueOf(N),K); } static Map<Long,Map<Integer,Long>> map=null; long dfs(long n,int k) { if(k==1) { return n; } if(n==0) { return 0; } Map<Integer,Long> t=map.get(n); if(t==null) { t=new HashMap<>(); map.put(n,t); } if(t.get(k)!=null) { return t.get(k); } long result=-1; for(int i=2;i<=5;++i) { long tmp=n%i+dfs(n/i,k-1); if(result==-1||result>tmp) { result=tmp; } } t.put(k,result); return result; } }