problem1 link
每次贪心地从crans由大到小地找到一个能搬得动地尽量大地box即可。
problem2 link
首先,$hava$可以全部换成钱,然后就是找到一个最小的钱减去自己已有的钱即可。
直接枚举所有的组合是会超时的,因为有$2^{n}$。可以分成两部分,各有一半,枚举出所有情况,记录$(SumPrice,SumValue)$。然后遍历前一半的所有情况,在后一半中搜索大于等于$K-SumValue$的组合中最小的$SumPrice$是多少。
problem3 link
首先,可以先得出所有的$forbidden$情况。令$m$为$forbidden$串的长度。
在构造一个长度为$wordLength$的串时要其合法,只需要每次最后长度为$m$的后缀不在$forbidden$集合里面即可。这样的话,可以用$f[n][mask]$表示已经构造了长度为$n$的串,最后的长度为$m-1$的suffix状态为$mask$的合法串的数量。
有了$f$数组,就可以构造出第$K$个合法串(假设下标从1开始)。比如$f[0][0] \geq K$时第一个字符就是‘A‘;否则就是‘B‘,然后K=K-f[0][0],继续判断下一个字符。
code for problem1
import java.util.*; import java.math.*; import static java.lang.Math.*; public class ShipLoading { public int minimumTime(int[] cranes, String[] boxes) { List<Integer> list=new ArrayList<>(); StringBuilder sb=new StringBuilder(); for(int i=0;i<boxes.length;++i) { sb.append(boxes[i]); } String[] a=sb.toString().split("\\W+"); for(String s:a) { if(s.trim().length()>0) { list.add(Integer.valueOf(s.trim())); } } Collections.sort(list); if(list.size()==0) { return 0; } Arrays.sort(cranes); if(list.get(list.size()-1)>cranes[cranes.length-1]) { return -1; } int num=0; int result=0; while(num<list.size()) { ++result; for(int j=cranes.length-1;j>=0;--j) { num+=get(list,cranes[j]); } } return result; } int get(List<Integer> list,int k) { for(int i=list.size()-1;i>=0;--i) { if(list.get(i)!=-1&&list.get(i)<=k) { list.set(i,-1); return 1; } } return 0; } }
code for problem2
import java.util.*; import java.math.*; import static java.lang.Math.*; public class CollectingPostmarks { static class pair { public long first; public long second; public pair() {} public pair(long x,long y) { first=x; second=y; } } static class MyComparator implements Comparator<pair> { public int compare(pair a,pair b) { if(a.second!=b.second) { return a.second<b.second?-1:1; } if(a.first==b.first) { return 0; } return a.first<b.first?-1:1; } } public int amountOfMoney(int[] prices, int[] have, int[] values, int K) { if(K==0) { return 0; } final int n=prices.length; final int m=have.length; long sum1=0,sum2=0,sum0=0; for(int i=0;i<n;++i) { sum1+=values[i]; sum0+=prices[i]; } for(int i=0;i<m;++i) { sum2+=prices[have[i]]; } if(sum1<K) { return -1; } if(n==1) { if(sum0<sum2) { return 0; } return (int)(sum0-sum2); } int[] p1=new int[n>>1]; int[] v1=new int[n>>1]; int[] p2=new int[n-p1.length]; int[] v2=new int[n-p1.length]; for(int i=0;i<n;++i) { if(i<p1.length) { p1[i]=prices[i]; v1[i]=values[i]; } else { p2[i-p1.length]=prices[i]; v2[i-p1.length]=values[i]; } } List<pair> l1=cal(p1,v1); List<pair> l2=cal(p2,v2); Collections.sort(l1,new MyComparator()); Collections.sort(l2,new MyComparator()); long minPrice=1l<<50; for(int i=l2.size()-1;i>=0;--i) { if(minPrice<l2.get(i).first){ l2.get(i).first=minPrice; } else { minPrice=l2.get(i).first; } } long minCost=1l<<50; for(int i=0;i<l1.size();++i) { pair t=l1.get(i); if(t.second>=K) { minCost=Math.min(minCost,t.first); continue; } minCost=Math.min(minCost,t.first+get(l2,K-t.second)); } if(sum2>minCost) { return 0; } return (int)(minCost-sum2); } long get(List<pair> list,long K) { final int n=list.size(); if(list.get(n-1).second<K) { return 1l<<50; } if(K<=list.get(0).second) { return list.get(0).first; } int low=0,high=n-1; int result=n-1; while(low<=high) { int mid=(low+high)>>1; if(list.get(mid).second>=K) { result=Math.min(result,mid); high=mid-1; } else { low=mid+1; } } return list.get(result).first; } List<pair> cal(int[] p,int[] v) { final int n=p.length; List<pair> list=new ArrayList<>(); for(int i=0;i<(1<<n);++i) { pair t=new pair(); t.first=t.second=0; for(int j=0;j<n;++j) { if((i&(1<<j))!=0) { t.first+=p[j]; t.second+=v[j]; } } list.add(t); } return list; } }
code for problem3
import java.util.*; import java.math.*; import static java.lang.Math.*; public class AlienDictionary { static final int INF=1000000005; boolean[] forbidden=new boolean[1<<17]; int n,m; int[][] f=new int[52][1<<16]; public String[] getWords(int wordLength, String[] forbiddenSubstrings, int[] wordNumbers) { this.n=wordLength; if(forbiddenSubstrings.length>0) { this.m=forbiddenSubstrings[0].length(); } else { m=1; } for(int i=0;i<forbiddenSubstrings.length;++i) { dfs(0,0,forbiddenSubstrings[i]); } for(int i=0;i<n;++i) { for(int j=0;j<(1<<(m-1));++j) { f[i][j]=-1; } } String[] result=new String[wordNumbers.length]; for(int i=0;i<wordNumbers.length;++i) { int k=wordNumbers[i]; if(cal(0,0)<=k) { result[i]=new String("NO PAGE"); continue; } StringBuilder sb=new StringBuilder(); int suffixMask=0; for(int id=0;id<n;++id) { suffixMask&=(1<<(m-1))-1; if(cal(id+1,suffixMask<<1)>k) { sb.append(‘A‘); suffixMask=suffixMask<<1; } else { sb.append(‘B‘); k-=cal(id+1,suffixMask<<1); suffixMask=suffixMask<<1|1; } } result[i]=sb.toString(); } return result; } int cal(int pos,int mask) { if(pos>=m&&forbidden[mask]) { return 0; } if(pos==n) { return 1; } mask&=(1<<(m-1))-1; if(f[pos][mask]!=-1) { return f[pos][mask]; } final int mask1=mask&((1<<(m-1))-1); int result=cal(pos+1,mask1<<1)+cal(pos+1,mask1<<1|1); if(result>INF) { result=INF; } return f[pos][mask]=result; } void dfs(int dep,int mask,String s) { if(dep==s.length()) { forbidden[mask]=true; return; } if(s.charAt(dep)!=‘B‘) { dfs(dep+1,mask<<1,s); } if(s.charAt(dep)!=‘A‘) { dfs(dep+1,mask<<1|1,s); } } }
时间: 2024-10-13 22:47:13