湖南2013第九届省赛解题报告(长期拖延更新中。。。)
偶尔做一题,做一题更新一题好了。。。
转化的时候记录每个字母在原串位置,对新串枚举中点,向两边枚举判近似回文,更新更长回文。
1 #include<stdio.h> 2 #include<string.h> 3 #include<stdlib.h> 4 #include<ctype.h> 5 const int maxn = 1011; 6 char buf[maxn]; 7 char as[maxn]; 8 int p[maxn]; 9 int k; 10 int main() 11 { 12 int i, j, start, maxlen, alen, neq, ca = 0; 13 while(scanf("%d", &k) != EOF) 14 { 15 gets(buf); 16 gets(buf); 17 for(i = j = 0; buf[i]; i ++) 18 if(isalpha(buf[i])) 19 { 20 as[j] = tolower(buf[i]); 21 p[j] = i; 22 j ++; 23 } 24 as[j] = 0; 25 alen = j; 26 maxlen = 0; 27 start = -1; 28 for(i = 0; as[i]; i ++) 29 { 30 for(j = neq = 0; i - j >= 0 && i + j < alen; j ++) 31 { 32 neq += as[i - j] != as[i + j]; 33 if(neq > k) break; 34 } 35 j --; 36 if(p[i + j] - p[i - j] + 1 > maxlen) 37 maxlen = p[i + j] - p[i - j] + 1, start = p[i - j]; 38 for(j = 1, neq = 0; i - j >= -1 && i + j < alen; j ++) 39 { 40 neq += as[i - j + 1] != as[i + j]; 41 if(neq > k) break; 42 } 43 j --; 44 if(j <= 0) continue; 45 if(p[i + j] - p[i - j + 1] + 1 > maxlen) 46 { 47 maxlen = p[i + j] - p[i - j + 1] + 1, start = p[i - j + 1]; 48 } 49 } 50 printf("Case %d: %d %d\n", ++ca, maxlen, start + 1); 51 } 52 return 0; 53 }
构造双向链表,按要求进行一系列链接操作,对反转加一个标记即可。
1 #include<stdio.h> 2 #include<string.h> 3 #include<stdlib.h> 4 #include<algorithm> 5 using namespace std; 6 const int maxn = 100111; 7 int turn; 8 struct Box 9 { 10 int lr[2]; 11 }; 12 Box b[maxn]; 13 int n, m, p, x, y; 14 void init(int n) 15 { 16 turn = 0; 17 b[0].lr[1] = 1; 18 for(int i = 1; i <= n + 1; i ++) 19 b[i].lr[0] = i - 1, b[i].lr[1] = i + 1; 20 } 21 int main() 22 { 23 int ca = 0; 24 long long ans; 25 while(scanf("%d%d", &n, &m) != EOF) 26 { 27 init(n); 28 while(m --) 29 { 30 scanf("%d", &p); 31 switch(p) 32 { 33 case 1: 34 scanf("%d%d", &x, &y); 35 b[b[x].lr[turn]].lr[!turn] = b[x].lr[!turn]; 36 b[b[x].lr[!turn]].lr[turn] = b[x].lr[turn]; 37 b[x].lr[turn] = b[y].lr[turn]; 38 b[x].lr[!turn] = y; 39 b[y].lr[turn] = x; 40 b[b[x].lr[turn]].lr[!turn] = x; 41 break; 42 case 2: 43 scanf("%d%d", &x, &y); 44 b[b[x].lr[turn]].lr[!turn] = b[x].lr[!turn]; 45 b[b[x].lr[!turn]].lr[turn] = b[x].lr[turn]; 46 b[x].lr[!turn] = b[y].lr[!turn]; 47 b[x].lr[turn] = y; 48 b[y].lr[!turn] = x; 49 b[b[x].lr[!turn]].lr[turn] = x; 50 break; 51 case 3: 52 scanf("%d%d", &x, &y); 53 if(b[x].lr[turn] != y && b[x].lr[!turn] != y) 54 { 55 b[b[x].lr[turn]].lr[!turn] = y; 56 b[b[x].lr[!turn]].lr[turn] = y; 57 b[b[y].lr[turn]].lr[!turn] = x; 58 b[b[y].lr[!turn]].lr[turn] = x; 59 swap(b[x], b[y]); 60 } 61 else 62 { 63 if(b[x].lr[turn] == y) swap(x, y); 64 b[b[x].lr[turn]].lr[!turn] = y; 65 b[b[y].lr[!turn]].lr[turn] = x; 66 b[x].lr[!turn] = b[y].lr[!turn]; 67 b[y].lr[turn] = b[x].lr[turn]; 68 b[x].lr[turn] = y; 69 b[y].lr[!turn] = x; 70 } 71 break; 72 case 4: 73 turn = !turn; 74 } 75 } 76 ans = 0; 77 int start, end, cnt; 78 if(!turn) start = 0, end = n + 1; 79 else start = n + 1, end = 0; 80 cnt = 0; 81 for(int i = start; i != end; i = b[i].lr[!turn], cnt ++) 82 { 83 if(cnt & 1) ans += i; 84 } 85 printf("Case %d: %lld\n", ++ca, ans); 86 } 87 return 0; 88 }
检查第四行星号的位置即可
1 #include<stdio.h> 2 int main() 3 { 4 char s[50]; 5 int i, n; 6 while(scanf("%d", &n) != EOF) 7 { 8 for(i = 0; i < 4; i ++) 9 scanf("%s", s); 10 for(i = 0; i < (n << 2); i += 4) 11 { 12 if(s[i] == '*') printf("2"); 13 else if(s[i + 1] == '*') printf("1"); 14 else printf("3"); 15 } 16 scanf("%s", s); 17 printf("\n"); 18 } 19 return 0; 20 }
首先明确,1、任何对角线,是否可以切割,与切割的步骤无关。2、任何边和切割的线,都肯定是某个三角形的一条边。
由此,预处理所有可切割的对角线,选一条边作为起始(p[0]~p[n-1]最合适,可保证start<end),其他的点与这条边可构成三角形。
如果这条三角形除了p[start]~p[end]这条边之外的两条边都是可切割边(或者有一条是多边形的边),则可分割子问题。
dp[start][end]表示p[start]~p[end]为起始边,与p[start~end]的这些点构成的多边形作为子问题切割之后的最优解。
这样,转移方程为dp[start][end] = dp[start][i] + dp[i][end] + Dis(p[start], p[i]) + Dis(p[i], p[end]),而有一条边是多边形边的时候特别处理一下。
另外判断是否为可切割对角线的时候,要注意1、对角线不与任何其他边规范相交。2、其他任何顶点不在对角线上。3、对角线不在多边形外部。
1 #include<stdio.h> 2 #include<stdlib.h> 3 #include<string.h> 4 #include<math.h> 5 const int maxn = 111; 6 const double eps = 1e-10; 7 const double inf = 1e20; 8 const double pi = acos(-1.0); 9 inline double dcmp(double x){return (x > eps) - (x < -eps);} 10 inline double min(double a, double b) {return a < b ? a : b;} 11 inline double max(double a, double b) {return a > b ? a : b;} 12 inline double Sqr(double x) {return x * x;} 13 struct Point 14 { 15 double x, y; 16 Point(){x = y = 0;} 17 Point(double a, double b){x = a, y = b;} 18 inline Point operator-(const Point &b)const 19 {return Point(x - b.x, y - b.y);} 20 inline Point operator+(const Point &b)const 21 {return Point(x + b.x, y + b.y);} 22 inline Point operator*(const double &b)const 23 {return Point(x * b, y * b);} 24 inline double Dis(const Point &b)const 25 {return sqrt(Sqr(x - b.x) + Sqr(y - b.y));} 26 inline double cross(const Point &b, const Point &c)const 27 {return (b.x - x) * (c.y - y) - (c.x - x) * (b.y - y);} 28 inline double dot(const Point &b)const 29 {return x * b.x + y * b.y;} 30 inline bool InLine(const Point &b, const Point &c)const 31 {return !dcmp(cross(b, c));} 32 inline bool OnSeg(const Point &b, const Point &c)const 33 {return InLine(b, c) && (*this - c).dot(*this - b) < eps;} 34 inline bool InSeg(const Point &b, const Point &c)const 35 {return InLine(b, c) && (*this - c).dot(*this - b) < -eps;} 36 }; 37 bool SegCross(const Point &a, const Point &b, const Point &c, const Point &d) 38 { 39 return dcmp(a.cross(b, c) * a.cross(b, d)) < 0 && dcmp(c.cross(d, a) * c.cross(d, b)) < 0; 40 } 41 Point p[maxn]; 42 int n; 43 double dp[maxn][maxn]; 44 bool vis[maxn][maxn]; 45 bool cancut[maxn][maxn]; 46 double DPS(int start, int end) 47 { 48 double &ans = dp[start][end]; 49 if(vis[start][end]) return ans; 50 vis[start][end] = true; 51 if(end - start <= 2) return ans = 0; 52 ans = inf; 53 int i; 54 if(cancut[start][end - 1]) 55 ans = min(ans, DPS(start, end - 1) + p[start].Dis(p[end - 1])); 56 if(cancut[start + 1][end]) 57 ans = min(ans, DPS(start + 1, end) + p[start + 1].Dis(p[end])); 58 for(i = start + 2; i < end - 1; i ++) 59 if(cancut[start][i] && cancut[i][end]) 60 ans = min(ans, DPS(start, i) + DPS(i, end) + p[start].Dis(p[i]) + p[i].Dis(p[end])); 61 return ans; 62 } 63 64 bool InSimplePolygon(Point u, Point p[], int n) 65 { 66 int flag = 0; 67 for(int i = 0; i < n; i++) 68 { 69 Point p1 = p[i]; 70 Point p2 = p[(i+1)%n]; 71 if(u.OnSeg(p1, p2)) return false; 72 int k = dcmp(p1.cross(p2, u)); 73 int d1 = dcmp(p1.y - u.y); 74 int d2 = dcmp(p2.y - u.y); 75 if(k > 0 && d1 <= 0 && d2 > 0) flag++; 76 if(k < 0 && d2 <= 0 && d1 > 0) flag--; 77 } 78 return flag != 0; 79 } 80 void InitCanCut() 81 { 82 memset(cancut, 0, sizeof(cancut)); 83 for(int i = 0; i < n; i ++) 84 for(int j = i + 2; j < n; j ++) 85 { 86 if(i == 0 && j == n - 1) continue; 87 int k = n; 88 for(k = 0; k < n; k ++) 89 { 90 if(SegCross(p[i], p[j], p[k], p[k + 1]) || (k != i && k != j && p[k].InSeg(p[i], p[j]))) 91 break; 92 } 93 if(k == n && InSimplePolygon((p[i] + p[j]) * 0.5, p, n)) cancut[i][j] = cancut[j][i] = true; 94 } 95 } 96 97 int main() 98 { 99 int ca = 0; 100 while(scanf("%d", &n) != EOF) 101 { 102 for(int i = 0; i < n; i ++) 103 scanf("%lf%lf", &p[i].x, &p[i].y); 104 p[n] = p[0]; 105 InitCanCut(); 106 memset(vis, 0, sizeof(vis)); 107 printf("Case %d: %.4f\n", ++ca, DPS(0, n - 1)); 108 } 109 return 0; 110 }