BottomCoder SRM 373 div2
points | result | time |
---|---|---|
250 | AC | 3.5m |
500 | AC | 11.5m |
1000 | AC | 13.2m |
後解き。
500がいい問題だった。
250
X,Y,P(<=1000)が与えられる。自然数a,bについて、aX+bYがPで割り切れるときのa+bの最小値を求めよ。ただし答えは2P以下になる。
一瞬面食らうが、最後の文のおかげで、a<=P, b<=Pで全走査すればいいとわかる。
public class TheEquation { public int leastSum(int X, int Y, int P) { int min = 2*P; for(int i = 1;i <= P;i++){ for(int j = 1;j <= P;j++){ if((i*X+j*Y)%P == 0 ){ min = Math.min(min, i+j); } } } return min; } }
500
先頭と末尾にスペースがない、スペースで区切られたtext(||<=50)が与えられる。これを7より大きいサイズのフォントで表示してwidth*height(<=10000*10000)に収めたい。ただしスペースの箇所しか改行に変えることはできず、フォントサイズがsのとき、1文字の横幅はs+2, 高さは2sとなる。収められる最大のフォントサイズを求めよ。そのようなサイズが存在しないときは-1を返せ。
フォントサイズを固定したときは、なるべく1行にたくさん収まるように詰めていく方針で埋めていけば良い。前もってスペースの位置をリストアップして(末尾も付け加えておく)おいて、現在のスペースまでで収まって、次のスペースで収まらない、あるいは次が存在しないところを探せばよい。
コードはsの二分探索でかいているが、答えはせいぜい5000までで、スペースの数も高々50/2個だろうから、線形探索でもよい。
import java.util.ArrayList; import java.util.List; public class StringFragmentation { int w, h; List<Integer> ss; public int largestFontSize(String text, int width, int height) { text += " "; ss = new ArrayList<Integer>(); for(int i = 0;i < text.length();i++){ if(text.charAt(i) == ' '){ ss.add(i); } } w = width; h = height; int inf = 7; int sup = 10001; while(sup - inf > 1){ int mid = (inf+sup)/2; if(ok(mid)){ inf = mid; }else{ sup = mid; } } return inf == 7 ? -1 : inf; } boolean ok(int n) { int m = ss.size(); int prev = 0; int hh = 0; for(int i = 0;i < m;i++){ if((n+2)*(ss.get(i)-prev) <= w){ if(i+1 >= m || (n+2)*(ss.get(i+1)-prev) > w){ prev = ss.get(i)+1; hh += 2*n; if(hh > h){ return false; } } }else{ return false; } } return true; } }
1000
互いに共有点を持たない長方形がN(<=50)個ある。また、M(<=50)本の線分が与えられる。このとき、"線分の端点の少なくとも1個が内部にあるような長方形の面積の合計"と、"線分の端点が1個も内部にないが、少なくとも1本の線分と交わっている長方形の面積の合計"を求めよ。
求める2種類両方の性質を持つ長方形は存在しない。よって、"線分の端点の少なくとも1個が内部にあるような長方形"を求めてから、
"少なくとも1本の線分と交わっている長方形"から上記の長方形たちをのぞけば良い。
後者の長方形を求める段では、両端とも長方形内部にあるようなものは後々除かれるので、必ず線分と長方形の辺のどれかは交わっていると考える。線分同士の交点は、Javaではine2D.intersectsLineを使えば楽勝である。
import java.awt.geom.Line2D; import java.util.BitSet; public class RectangleCrossings { // 13.2 public int[] countAreas(String[] rectangles, String[] segments) { int n = rectangles.length; int m = segments.length; int[][] rect = new int[n][4]; int[][] seg = new int[m][4]; for(int i = 0;i < n;i++){ String[] sp = rectangles[i].split(" "); for(int j = 0;j < 4;j++){ rect[i][j] = Integer.parseInt(sp[j]); } } for(int i = 0;i < m;i++){ String[] sp = segments[i].split(" "); for(int j = 0;j < 4;j++){ seg[i][j] = Integer.parseInt(sp[j]); } } BitSet end = new BitSet(); for(int j = 0;j < m;j++){ for(int i = 0;i < n;i++){ if(rect[i][0] < seg[j][0] && seg[j][0] < rect[i][2] && rect[i][1] < seg[j][1] && seg[j][1] < rect[i][3]){ end.set(i); break; } } for(int i = 0;i < n;i++){ if(rect[i][0] < seg[j][2] && seg[j][2] < rect[i][2] && rect[i][1] < seg[j][3] && seg[j][3] < rect[i][3]){ end.set(i); break; } } } BitSet inter = new BitSet(); for(int j = 0;j < m;j++){ for(int i = 0;i < n;i++){ if(Line2D.linesIntersect(seg[j][0], seg[j][1], seg[j][2], seg[j][3], rect[i][0], rect[i][1], rect[i][0], rect[i][3]))inter.set(i); if(Line2D.linesIntersect(seg[j][0], seg[j][1], seg[j][2], seg[j][3], rect[i][0], rect[i][3], rect[i][2], rect[i][3]))inter.set(i); if(Line2D.linesIntersect(seg[j][0], seg[j][1], seg[j][2], seg[j][3], rect[i][2], rect[i][1], rect[i][2], rect[i][3]))inter.set(i); if(Line2D.linesIntersect(seg[j][0], seg[j][1], seg[j][2], seg[j][3], rect[i][0], rect[i][1], rect[i][2], rect[i][1]))inter.set(i); } } inter.andNot(end); int se = 0, si = 0; for(int i = end.nextSetBit(0);i != -1;i = end.nextSetBit(i+1)){ se += (rect[i][3] - rect[i][1]) * (rect[i][2] - rect[i][0]); } for(int i = inter.nextSetBit(0);i != -1;i = inter.nextSetBit(i+1)){ si += (rect[i][3] - rect[i][1]) * (rect[i][2] - rect[i][0]); } return new int[]{se, si}; } }