湖南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

 

 

你可能感兴趣的:(更新)