srm539 div1
2012-04-30 11:13 macaroniz 阅读(155) 评论(0) 收藏 举报250pt
可以很容易想到,如果在确定用哪些box之后,我们可以直接算出该情况下x的范围 sum{low[i]} <= x <= sum{upper[i]}。
因此,只需要枚举一下所有选择box的方案,就可以求出这么一系列的x的范围。
但是由于这些范围可能存在区间重叠,因此我们需要按照(low,upper)排序后合并区间,因此我们只需要维护一个nowlow和nowUpper即可。
总的复杂度为O(15*2^15+2^15)
class Over9000Rocks { public: struct st { int low,upper; }; vector<st> arr1,arr2; static bool cmp(const st &a,const st &b) { if(a.low != b.low) return a.low < b.low; else return a.upper < b.upper; } int countPossibilities(vector <int> lowerBound, vector <int> upperBound) { int ans = 0; int maxstate = 1 << lowerBound.size(); arr1.clear(); arr2.clear(); for(int state = 0;state < maxstate;state++) { int low = 0,upper = 0; for(int i = 0;(1 << i) <= state;i++) { if(((1 << i) & state) != 0) { low += lowerBound[i]; upper += upperBound[i]; } } arr1.push_back((st){low,upper}); //printf("%d %d\n",low,upper); } sort(arr1.begin(),arr1.end(),cmp); int lows= arr1[0].low; int uppers = arr1[0].upper; for(int i = 1;i < arr1.size();i++) if(arr1[i].low > uppers) { arr2.push_back((st){lows,uppers}); lows = arr1[i].low; uppers = arr1[i].upper; } else if(arr1[i].upper > uppers) uppers= arr1[i].upper; arr2.push_back((st){lows,uppers}); for(int i = 0;i < arr2.size();i++) { if(arr2[i].upper > 9000) ans += arr2[i].upper - (arr2[i].low > 9001 ? arr2[i].low : 9001) + 1; } return ans; } };
550pt
首先这里有一个重要的结论,单源点最短路集合的并是一个有向无环图,也就是说,我们求出了0到其他所有点的最短路之后,定向一下,再将所有最短路合并之后构成一个新的图G,那么G是DAG图。
然后问题就很像是求图G的最小路径覆盖了,但是这里有一个问题,就是该题只需要覆盖1~N这N个顶点,但是图G中很可能存在N+1~K的顶点,因此为了转化到求最小路径覆盖的模型上,我们就需要将N+1~K这些顶点去掉,但是又不改变图G的联通性质。
这里还有一个重要的观察,如果i,j(i <=N,j<=N)之间在图G中有联通,且他们之间存在最短路p1->p2->...pm,且p1,p2....pm都是N+1~K中的顶点,那么我们可以直接在i,j之间连一条边。这样既去掉了N+1~K这些顶点,也不会改变G的连通性质,实际上,我们只需要在构图的时候,判断dist[0][i] == dist[0][j] + dist[i][j],即可确定i,j之间是否有边了。
至此,问题已经转化为了经典的求DAG图最小路径覆盖的问题。
const int oo = 10000000; class SafeReturn { public: int dist[55][55]; int mat2[55][55]; int vis[55]; int belong[55]; int N; bool find(int v) { for(int i = 0;i < N;i++) if(mat2[v][i] == 1 && vis[i] == 0) { //printf("%d %d\n",v,i); vis[i] = 1; if(belong[i] == -1 || find(belong[i])) { belong[i] = v; return true; } } return false; } int minRisk(int _N, vector <string> streets) { //$CARETPOSITION$ memset(dist,0,sizeof(dist)); N = _N; for(int i = 0;i < streets.size();i++) for(int j = 0;j < streets[i].length();j++) { if(streets[i][j] !='-') dist[i][j] = streets[i][j] - '0'; else dist[i][j] = oo; } for(int i = 0;i < streets.size();i++) dist[i][i] = 0; for(int k = 0;k < streets.size();k++) for(int i = 0;i < streets.size();i++) for(int j = 0;j < streets.size();j++) if(dist[i][j] > dist[i][k] + dist[k][j]) dist[i][j] = dist[i][k] + dist[k][j]; for(int i = 0;i <= N;i++) memset(mat2,0,sizeof(mat2)); for(int i = 1;i <= N;i++) for(int j = 1;j <= N;j++) if(i != j && dist[0][i] == dist[0][j] + dist[i][j]) mat2[j-1][i-1] = 1; int ans = 0; memset(belong,0xff,sizeof(belong)); for(int i = 0;i < N;i++) { memset(vis,0,sizeof(vis)); if(find(i)) ans++; } return N-ans; } };
1000pt
浙公网安备 33010602011771号