A
裸最短路.
1 class TravelOnMars { 2 public: 3 int minTimes(vector <int>, int, int); 4 }; 5 vector<int> e[maxn]; 6 int n; 7 8 int dist(int a,int b) { 9 if (a>b) swap(a,b); 10 int res = min( b-a , a+n-b); 11 return res; 12 } 13 int d[maxn],inq[maxn]; 14 queue<int> q; 15 int bfs(int s,int t) { 16 for (int i=0 ; i<n ; i++ ) d[i] = 1000; 17 d[s] = 0; 18 inq[s] = true; 19 q.push(s); 20 while (!q.empty()) { 21 int cur = q.front(); q.pop(); 22 printf("d[%d]:%d\n",cur,d[cur]); 23 inq[cur] = false; 24 for (int i=0 ; i<(int)e[cur].size() ; i++ ) { 25 int v = e[cur][i]; 26 if (d[v]>d[cur]+1) { 27 d[v] = d[cur]+1; 28 if (!inq[v]) { 29 inq[v] = true; 30 q.push(v); 31 } 32 } 33 } 34 } 35 return d[t]; 36 } 37 int TravelOnMars::minTimes(vector <int> range, int startCity, int endCity) { 38 n = range.size(); 39 printf("n=%d\n",n); 40 for (int i=0 ; i<n ; i++ ) { 41 for (int j=0 ; j<n ; j++ ) if (dist(i,j)<=range[i]) { 42 e[i].push_back(j); 43 } 44 } 45 int ans = bfs(startCity,endCity); 46 return ans; 47 }
B
f(u,s)表示以u为根子树的答案 , s=1表示有从u祖先下来的路径 , s=0表示没有.
f(u,s) 可以通过一个dp得到 :
dp[i][size]表示现在考虑第u的i个孩子,当前已经向下连了size条边时的最小代价 , 答案就是min(dp[ cntson ] [ size ] ),
然后需要加一些强制转移.
1 #include <vector> 2 #include <list> 3 #include <map> 4 #include <set> 5 #include <deque> 6 #include <stack> 7 #include <bitset> 8 #include <algorithm> 9 #include <functional> 10 #include <numeric> 11 #include <utility> 12 #include <sstream> 13 #include <iostream> 14 #include <iomanip> 15 #include <cstdio> 16 #include <cmath> 17 #include <cstdlib> 18 #include <ctime> 19 #include <cstring> 20 using namespace std; 21 #define maxn 55 22 class TurnOnLamps { 23 public: 24 int minimize(vector <int>, string, string); 25 }; 26 struct edge{ 27 int v,c; 28 }; 29 30 vector<edge> e[maxn]; 31 bool debug; 32 int var[maxn],n,dp[maxn][2],dp2[2][maxn][maxn]; 33 int getvar(int x) { 34 if (x<0) return 0; 35 int res = x/2 + (x&1); 36 if (debug) printf("var:%d = %d\n",x,res); 37 return res; 38 } 39 int better(int a,int b) { 40 if (a==-1) return b; 41 if (b==-1) return a; 42 return min(a,b); 43 } 44 int dfs(int u,int s,int fa) { 45 if (dp[u][s]!=-1) return dp[u][s]; 46 vector<edge> son; 47 for (int i=0 ; i<(int)e[u].size() ; i++ ) { 48 int v = e[u][i].v; 49 if (v==fa) continue; 50 son.push_back(e[u][i]); 51 dfs(v,0,u); 52 dfs(v,1,u); 53 } 54 debug = (u==10); 55 printf("u:%d s:%d debug=%d\n",u,s,debug); 56 for (int i=0 ; i<(int)e[u].size() ; i++ ) if (e[u][i].v != fa) { 57 printf("son:%d c:%d\n",e[u][i].v,e[u][i].c); 58 } 59 // {{0, 1, 0, 2, 0, 1, 1, 2, 4, 6, 10, 10, 11, 10, 9, 9, 10, 15, 7}, "0111100111001010000", "0100001100101000111"} 60 int res = 0; 61 // for (int i=0 ; i<son.size() ; i++ ) printf("%d %d\n",son[i].v,son[i].c); 62 if (son.size()) { 63 if (son[0].c==0) { 64 dp2[s][son[0].v][0] = dp[son[0].v][0]; 65 dp2[s][son[0].v][1] = dp[son[0].v][1] + getvar(1-s); 66 } else if (son[0].c==1) { 67 dp2[s][son[0].v][1] = dp[son[0].v][1] + getvar(1-s); 68 } else if (son[0].c==2) { 69 dp2[s][son[0].v][0] = dp[son[0].v][0]; 70 } 71 for (int i=1 ; i<(int)son.size() ; i++ ) { 72 int lastv = son[i-1].v; 73 int v = son[i].v; 74 int c = son[i].c; 75 for (int j=0 ; j<=i ; j++ ) if (dp2[s][lastv][j] != -1) { 76 if (u==10) printf("dp2[%d][%d][%d]=%d\n",s,lastv,j,dp2[s][lastv][j]); 77 // printf("dp2[%d][%d]=%d\n",lastv,j,dp2[lastv][j]); 78 if (c == 0) { 79 int tmp; 80 tmp = better(dp2[s][v][j] , dp2[s][lastv][j]+dp[v][0]); 81 // if (u==10) printf("update: dp2[%d][%d][%d] from %d to %d\n",s,v,j,dp2[s][v][j],tmp); 82 dp2[s][v][j] = tmp; 83 tmp = better(dp2[s][v][j+1] , dp2[s][lastv][j]-getvar(j-s)+dp[v][1]+getvar(j+1-s)); 84 // if (u==10) printf("update: dp2[%d][%d][%d] from %d to %d\n",s,v,j+1,dp2[s][v][j+1],tmp); 85 dp2[s][v][j+1] = tmp; 86 } else if (c == 1) { 87 int tmp = better(dp2[s][v][j+1] , dp2[s][lastv][j]-getvar(j-s)+dp[v][1]+getvar(j+1-s)); 88 // if (u==10) printf("update: dp2[%d][%d][%d] from %d to %d\n",s,v,j+1,dp2[s][v][j+1],tmp); 89 dp2[s][v][j+1] = tmp; 90 } else if (c == 2) { 91 int tmp = dp2[s][v][j] = better(dp2[s][v][j] , dp2[s][lastv][j]+dp[v][0]); 92 // if (u==10) printf("update: dp2[%d][%d][%d] from %d to %d\n",s,v,j,dp2[s][v][j],tmp); 93 dp2[s][v][j] = tmp; 94 } 95 } 96 } 97 int smlcost = -1; 98 int v = son[son.size()-1].v; 99 for (int i=0 ; i<=(int)son.size() ; i++ ) 100 if (dp2[s][v][i]!=-1) { 101 smlcost = better(smlcost , dp2[s][v][i]); 102 } 103 // if (smlcost != -1) res = smlcost; 104 res = smlcost; 105 } 106 printf("dp[%d][%d]=%d\n",u,s,res); 107 return dp[u][s] = res; 108 } 109 int TurnOnLamps::minimize(vector <int> roads, string init, string imp) { 110 n = roads.size()+1; 111 for (int i=0 ; i<n-1 ; i++ ) { 112 e[i+1].push_back((edge){roads[i],imp[i]=='1'?imp[i]-'0'+init[i]-'0':0}); 113 e[roads[i]].push_back((edge){i+1,imp[i]=='1'?imp[i]-'0'+init[i]-'0':0}); 114 } 115 memset(dp,-1,sizeof(dp)); 116 memset(dp2,-1,sizeof(dp2)); 117 int ans = dfs(0,0,-1); 118 return ans; 119 }
C
概率题好费脑筋啊。。
模拟样例算不对 , 后来发现是少算了转移到自己的情况 , 然后就不会做了: 考虑每次能转移到自己的情况会出现无数步 , 怎么计算期望就成了问题;
题解在这个问题上处理地很巧妙 :
(1) 从期望的公式出发,推导得到了一个简单的形式 : sum ( 第i步没有完成的概率 ) (0<=i <INF);
(2) 可以用容斥来计算第i步没有完成的概率;
(3) 将容斥的公式变形 , 得到一系列的收敛的无穷级数 , 于是解决了i有无穷多的问题;
最后就得到了一个简单的统计模型: 对于给定的值x , 求有多少个元素个数为奇数的集合sum为x , 和有多少个个数为偶数的集合sum为x , 求他们的差,递推即可.
1 #define maxn 2000 2 class RandomPaintingOnABoard { 3 public: 4 double expectedSteps(vector <string>); 5 }; 6 int cnt[maxn],sum[maxn],n,m,f[30][maxn],tot; 7 double RandomPaintingOnABoard::expectedSteps(vector <string> prob) { 8 n = prob.size(); 9 m = prob[0].size(); 10 vector<string> tmp; 11 if (m>n) { 12 for (int i=0 ; i<m ; i++ ) { 13 string s = ""; 14 for (int j=0 ; j<n ; j++ ) s += prob[j][i]; 15 tmp.push_back(s); 16 } 17 prob = tmp; 18 swap (n,m); 19 for (int i=0 ; i<n ; i++ ) cout<<prob[i]<<endl; 20 } 21 double ans = 0; 22 printf("n:%d m:%d\n",n,m); 23 for (int i=0 ; i<n ; i++ ) for (int j=0 ; j<m ; j++ ) tot += prob[i][j]-'0'; 24 for (int i=0 ; i<(1<<m) ; i++ ) { 25 26 // for (int j=0 ; j<n ; j++ ) sum[j] = 0; 27 // for (int j=0 ; j<n ; j++ ) for (int k=0 ; k<=tot ; k++ ) f[j][k] = 0; 28 memset(sum,0,sizeof(sum)); 29 memset(f,0,sizeof(f)); 30 31 for (int j=0 ; j<n ; j++ ) for (int k=0 ; k<m ; k++ ) if (((i>>k)&1)==0) { 32 sum[j] += prob[j][k]-'0'; 33 } 34 f[0][0] = -1; 35 for (int j=0 ; j<m ; j++ ) if ((i>>j)&1) f[0][0] *= -1; 36 for (int j=0 ; j<n ; j++ ) for (int k=0 ; k<=tot ; k++ ) { 37 f[j+1][k] -= f[j][k]; 38 if (k+sum[j]<=tot) f[j+1][k+sum[j]] += f[j][k]; 39 } 40 for (int j=0 ; j<tot ; j++ ) cnt[j] += f[n][j]; 41 } 42 for (int i=0 ; i<tot ; i++ ) { 43 ans += (double)cnt[i] * ((double)tot/(double)(tot-i)); 44 } 45 return ans; 46 } 47 48 49 //Powered by [KawigiEdit] 2.0!