topcoder srm 425 div1
problem1 link
暴力搜索即可。
problem2 link
可以将每次所有的piece的位置看作一个状态,由于$C_{25}^{5}=53130$,所以最多有这么多状态。这里可以加一些优化来减少状态。比如通过旋转或者翻转是一样的状态其结果是一样的。
然后进行bfs即可。
problem3 link
对于一个状态$mask$来说,可以将其分成两个子状态$S_{1},S_{2}=mask-S_{1}$.为了防止重复,可以令两个固定的点$u_{1} \in S_{1},v_{1} \in S_{2}$.
$S_{1}={u_{1},u_{2},...,u_{n}}$
$S_{2}={v_{1},v_{2},...,v_{m}}$
那么$f[mask]=f[S_{1}]*f[S_{2}]*X*Y$
$X=\sum_{i=1}^{m}(p_{u_{1},v_{i}}*\sum_{x \in{S2-v_{i}}}(1-p_{u_{1},x}))$
$Y=\prod_{i=2}^{n}\prod _{x\in S_{2}}(1-p_{u_{i},x})$
code for ploblem1
import java.util.*; import java.math.*; import static java.lang.Math.*; public class CrazyBot { boolean[][] f=null; double[] p=new double[4]; final int[] dx={0,0,-1,1}; final int[] dy={1,-1,0,0}; double result=0.0; int n; public double getProbability(int n, int east, int west, int south, int north) { this.n=n; f=new boolean[2*n+1][2*n+1]; p[0]=east/100.0; p[1]=west/100.0; p[2]=south/100.0; p[3]=north/100.0; dfs(n,n,0,1.0); return result; } void dfs(int x,int y,int step,double prob) { if(step==n) { result+=prob; return; } f[x][y]=true; for(int i=0;i<4;++i) { int xx=x+dx[i]; int yy=y+dy[i]; if(!f[xx][yy]) { dfs(xx,yy,step+1,prob*p[i]); } } f[x][y]=false; } }
code for ploblem2
import com.sun.org.apache.xpath.internal.operations.Bool; import java.net.Inet4Address; import java.util.*; import java.math.*; import java.util.regex.Pattern; import static java.lang.Math.*; public class PiecesMover { static class Pair { public int x; public int y; public Pair() {} public Pair(int x,int y){ this.x=x; this.y=y; } } int index(int x,int y) { return x*5+y; } int index(Pair p) { return p.x*5+p.y; } Pair revIndex(int t) { return new Pair(t/5,t%5); } Map<Integer,Integer> map=new HashMap<>(); Map<Integer,Integer> map1=new HashMap<>(); List<Integer> map2=new ArrayList<>(); List<Boolean> stopStatus=new ArrayList<>(); int n=0; public int getMinimumMoves(String[] board) { int startMask=0; for(int i=0;i<5;++i) { for(int j=0;j<5;++j) { if(board[i].charAt(j)=='*') { startMask|=1<<index(i,j); ++n; } } } if(n==1) { return 0; } Pair[] all=new Pair[n]; for(int i=0;i<n;++i) { all[i]=new Pair(); } dfs(0,0,0,0,all); return bfs(startMask); } int bfs(int startMask) { int[] f=new int[map2.size()]; boolean[] inq=new boolean[map2.size()]; for(int i=0;i<f.length;++i) { f[i]=-1; } startMask=map.get(startMask); Queue<Integer> queue=new LinkedList<>(); int id=map1.get(startMask); queue.offer(id); f[id]=0; inq[id]=true; int result=1<<20; final int[] dx={0,0,1,-1}; final int[] dy={1,-1,0,0}; while(!queue.isEmpty()) { final int u=queue.poll(); inq[u]=false; if(stopStatus.get(u)) { result=Math.min(result,f[u]); continue; } final int mask=map2.get(u); for(int i=0,num=0;i<25&&num<n;++i) { if((mask&(1<<i))==0) { continue; } ++num; final int xx=revIndex(i).x; final int yy=revIndex(i).y; for(int d=0;d<4;++d) { final int nx=xx+dx[d]; final int ny=yy+dy[d]; if(nx<0||nx>=5||ny<0||ny>=5||(mask&(1<<index(nx,ny)))!=0) { continue; } final int nMask=map.get(mask^(1<<i)|(1<<index(nx,ny))); final int v=map1.get(nMask); if(f[v]==-1||f[u]+1<f[v]) { f[v]=f[u]+1; if(!inq[v]) { inq[v]=true; queue.offer(v); } } } } } return result; } void dfs(int x,int y,int id,int mask,Pair[] all) { if(id==n) { deal(mask,all); return; } if(y==5) { y=0; ++x; } if(x==5) { return; } all[id].x=x; all[id].y=y; dfs(x,y+1,id+1,mask|1<<index(x,y),all); dfs(x,y+1,id,mask,all); } int getMaks(Pair[] p) { int mask=0; for(int i=0;i<p.length;++i) { mask|=1<<index(p[i]); } return mask; } void deal(int mask,Pair[] all) { if(map.containsKey(mask)) { return; } int[] tMask=new int[6]; tMask[0]=reverseX(all); tMask[1]=reverseY(all); for(int i=0;i<4;++i) { all=rotate(all); tMask[i+2]=getMaks(all); } int minMask=tMask[0]; for(int i=1;i<6;++i) { minMask=Math.min(minMask,tMask[i]); } map1.put(minMask,map2.size()); for(int i=0;i<6;++i) { map.put(tMask[i],minMask); } map2.add(minMask); stopStatus.add(isStopStatus(all)); } boolean isStopStatus(Pair[] all) { int t=1; List<Integer> list=new ArrayList<>(); list.add(0); while(list.size()>0) { List<Integer> list1=new ArrayList<>(); for(int i=0;i<all.length;++i) { if((t&(1<<i))!=0) { continue; } for(int j=0;j<list.size();++j) { if(isAdj(all[i],all[list.get(j)])) { list1.add(i); t|=1<<i; break; } } } list=list1; } return t==((1<<all.length)-1); } boolean isAdj(Pair a,Pair b) { if(a.x==b.x) { return Math.abs(a.y-b.y)<=1; } if(b.y==a.y) { return Math.abs(a.x-b.x)<=1; } return false; } int reverseX(Pair[] all) { int mask=0; for(int i=0;i<all.length;++i) { mask|=1<<index(all[i].x,4-all[i].y); } return mask; } int reverseY(Pair[] all) { int mask=0; for(int i=0;i<all.length;++i) { mask|=1<<index(4-all[i].x,all[i].y); } return mask; } Pair[] rotate(Pair[] all) { for(int i=0;i<all.length;++i) { int x=all[i].x; int y=all[i].y; all[i].x=4-y; all[i].y=x; } return all; } }
code for ploblem3
import java.util.*; import java.math.*; import static java.lang.Math.*; public class RoadsOfKingdom { double[][] prob=null; int n; double[][] f1=null; double[][] f2=null; boolean[] visited=null; double[] dp=null; public double getProbability(String[] roads) { n=roads.length; prob=new double[n][n]; for(int i=0;i<n;++i) { for(int j=0;j<n;++j) { prob[i][j]=(roads[i].charAt(j)-'0')/8.0; } } f1=new double[1<<n][n]; f2=new double[1<<n][n]; for(int i=0;i<(1<<n);++i) { for(int j=0;j<n;++j) { f1[i][j]=1; f2[i][j]=0; for(int k=0;k<n;++k) { if((i&(1<<k))!=0) { f1[i][j]*=1-prob[k][j]; f2[i][j]+=f1[i^(1<<k)][j]*prob[j][k]; } } } } visited=new boolean[1<<n]; dp=new double[1<<n]; return dfs((1<<n)-1); } double dfs(int mask) { if(visited[mask]) { return dp[mask]; } int p1=-1,p2=-1; for(int i=0;i<n;++i) { if((mask&(1<<i))!=0) { if(p1==-1) { p1=i; } else if(p2==-1) { p2=i; break; } } } if(p2==-1) { return 1; } final int S=mask^(1<<p1)^(1<<p2); double result=0; for(int sub=S;;sub=(sub-1)&S) { final int S1=sub|1<<p1; final int S2=mask^S1; double x=1; for(int i=0;i<n;++i) { if(i!=p1&&(S1&(1<<i))!=0) { x*=f1[S2][i]; } } result+=dfs(S1)*dfs(S2)*f2[S2][p1]*x; if(0==sub) { break; } } visited[mask]=true; return dp[mask]=result; } }