湖南2013第九届省赛解题报告(长期拖延更新中。。。)

偶尔做一题,做一题更新一题好了。。。

 

A、COJ1328: 近似回文词

转化的时候记录每个字母在原串位置,对新串枚举中点,向两边枚举判近似回文,更新更长回文。

 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 }
View Code

 

B、COJ1329: 一行盒子

构造双向链表,按要求进行一系列链接操作,对反转加一个标记即可。

 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 }
View Code

 

C、COJ1330: 字符识别?

检查第四行星号的位置即可

 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 }
View Code

E、COJ1332: 割耳法

首先明确,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 }
View Code

 

 

posted @ 2013-10-27 19:36  CSGrandeur  阅读(425)  评论(0编辑  收藏  举报