A
只有3种情况:200以上的单独装,3个100的装一起,某两个u,v装一起且u+v<=300,
所以做法是从大到小判断每个大小的最大能与它装一起的是谁,最后剩下100的特判.
B
第一轮如果未分出胜负,考虑一种情况:
mov1 >= mov2, 先手至少不会输.
再判断赢的条件, 设d=mov1-mov2, 先手每一轮结束后可以保证每次距离缩短[1,d],但同时
先手要保持一个安全距离safe以保证不会被后手反击:
safe >= mov2+rng2,
所以当 safe + mov2 <= mov1+d时先手必胜,否则平局.
后手的推理类似.
1 string FoxAndFencing::WhoCanWin(int m1, int m2, int r1, int r2, int d) 2 { 3 if (d<=r1+m1) return "Ciel"; 4 else if (d+m1<=r2+m2) return "Liss"; 5 else if (m2==m1) return "Draw"; 6 else if (m1>m2) 7 { 8 if (r1+m1-2*m2>r2) return "Ciel"; 9 else return "Draw"; 10 }else 11 { 12 printf("%d+%d , %d\n",r2,m2,r1); 13 if (r2+m2-2*m1>r1) return "Liss"; 14 else return "Draw"; 15 } 16 }
C
首先发现一个性质: 如果某节点x有cnt个孩子,那么往下递归至少有cnt-1个子树存在标记,
这样才能保证x的子树都被识别,根据这条性质设计dp[i][0/1]即可.
但是仅仅这样dp会发现最后结果有一条从根到某叶子的未被标记的链,这条链的某些点可能不会被识别,
为了修正这个问题,可以强制根被标记,换句话说,可以枚举某个被标记的点为根.
1 #define maxn 51 2 class TPS { 3 public: 4 int minimalBeacons(vector <string>); 5 }; 6 int dp[maxn][2],n,cnts[maxn]; 7 int dfs(int cur,int must,int fa,vector<string> e) 8 { 9 int sum=0,tmp,res; 10 if (dp[cur][must]!=-1) return dp[cur][must]; 11 if (cnts[cur]==0) return dp[cur][must]=must; 12 for (int i=0 ; i<n ; i++ ) if (e[cur][i]=='Y' && i!=fa) 13 sum += dfs(i,1,cur,e); 14 tmp=sum; 15 for (int i=0 ; i<n ; i++ ) if(e[cur][i]=='Y' && i!=fa) 16 tmp = min(tmp,sum-dp[i][1]+dfs(i,0,cur,e)); 17 if (must && cnts[cur]==1) res = sum; 18 else res = tmp; 19 if (fa==-1) res++; 20 return dp[cur][must]=res; 21 } 22 void initson(int cur,int fa,vector<string> e) 23 { 24 for (int i=0 ; i<n ; i++ ) 25 if (e[cur][i]=='Y' && i!=fa) 26 { 27 cnts[cur]++; 28 initson(i,cur,e); 29 } 30 } 31 int TPS::minimalBeacons(vector <string> e) 32 { 33 n = e.size(); 34 int ans = n; 35 for (int i=0 ; i<n ; i++ ) 36 { 37 memset(dp,-1,sizeof(dp)); 38 memset(cnts,0,sizeof(cnts)); 39 initson(i,-1,e); 40 ans = min(ans,dfs(i,0,-1,e)); 41 } 42 return ans; 43 }