码迷,mamicode.com
首页 > 其他好文 > 详细

CodeForces Round #286 Div.2

时间:2015-01-25 13:46:57      阅读:174      评论:0      收藏:0      [点我收藏+]

标签:

A. Mr. Kitayuta‘s Gift (枚举)

题意:

给一个长度不超过10的串,问能否通过插入一个字符使得新串成为回文串。

分析:

因为所给的串很多,所以可以枚举 “在哪插入” 和 “插入什么”,写一个二重循环枚举新串,判断是否为回文串。时间复杂度为O(n3)

还可只枚举插入位置(在那个位置用一个特殊字符表示),在判断的时候,如果遇到特殊字符,则所插入的字符一定为镜像的字符。

技术分享
 1 #include <cstdio>
 2 #include <cstring>
 3 
 4 char s[15], s1[15];
 5 int l;
 6 
 7 bool judge()
 8 {
 9     for(int i = 0; i < (l+1)/2; ++i)
10         if(s1[i] == 0) s1[i] = s1[l-i];
11         else if(s1[l-i] == 0) s1[l-i] = s[i];
12         else if(s1[i] != s1[l-i]) return false;
13 
14     return true;
15 }
16 
17 int main()
18 {
19     scanf("%s", s);
20     l = strlen(s);
21     bool flag = false;
22     for(int pos = 0; pos <= l; ++pos)
23     {//枚举所加入字符的位置,s1为得到的新串
24         int i;
25         for(i = 0; i < pos; ++i) s1[i] = s[i];
26         s1[i++] = 0;
27         for(; i <= l; ++i)s1[i] = s[i-1];
28         if(judge()) { flag = true; break; }
29     }
30 
31     if(!flag) puts("NA");
32     else
33     {
34         for(int i = 0; i <= l; ++i)
35             if(s1[i] == 0) printf("a");
36             else printf("%c", s1[i]);
37     }
38 
39     return 0;
40 }
代码君

 

B. Mr. Kitayuta‘s Colorful Graph (并查集)

题意:

有一个多种颜色的无向图,给出每条边的两个顶点以及该边的颜色。

然后有若干次询问,每次询问两点间共有多少种颜色的通路。

分析:

这道题可以理解为二维的并查集。如果没有颜色的区分,可以判断两点是否连通。

现在给边染上颜色,则我们可以分开处理。最后在询问的时候枚举所有颜色,判断两点是否连通。

技术分享
 1 #include <cstdio>
 2 #include <vector>
 3 #include <cstring>
 4 #include <algorithm>
 5 using namespace std;
 6 
 7 const int maxn = 100  + 10;
 8 
 9 int G[maxn][maxn];
10 int n, m;
11 int p[maxn][maxn];
12 //找颜色为color的边中,x的父节点
13 int findp(int color, int x) { return x == p[color][x] ? x : p[color][x] = findp(color, p[color][x]); }
14 
15 struct Edge
16 {
17     int u, v;
18     Edge(int u=0, int v=0):u(u), v(v) {}
19 };
20 
21 vector<Edge> edges[maxn];
22 
23 int main()
24 {
25     //freopen("in.txt", "r", stdin);
26     int n, m, Mc = 0;
27     scanf("%d%d", &n, &m);
28     //并查集初始化
29     for(int i = 1; i <= m; ++i)
30         for(int j = 1; j <= n; ++j)
31             p[i][j] = j;
32 
33     for(int i = 0; i < m; ++i)
34     {
35         int a, b, c;
36         scanf("%d%d%d", &a, &b, &c);
37         Mc = max(Mc, c);
38         int pa = findp(c, a);
39         int pb = findp(c, b);
40         if(pa != pb) p[c][pa] = pb;
41     }
42 
43     int Q;
44     scanf("%d", &Q);
45     for(int i = 0; i < Q; ++i)
46     {
47         int u, v, cnt = 0;
48         scanf("%d%d", &u, &v);
49         for(int c = 1; c <= Mc; ++c) //枚举所有颜色
50             if(findp(c, u) == findp(c, v))
51                 cnt++;
52         printf("%d\n", cnt);
53     }
54 
55     return 0;
56 }
代码君

 

C. Mr. Kitayuta, the Treasure Hunter (DP)

题意:

参见原文吧,=_=||

Mr. Kitayuta, the Treasure Hunter

分析:

设dp(i, j)表示跳到第i个岛步长为j,wi表示第i个岛的宝石数,最大能取到的宝石数。

状态转移方程为 dp(i, j) = wi + max{dp(i+j-1, j-1), dp(i+j, j), dp(i+j+1, j+1)}

上式是从后往前推的,最终答案是dp(d, d)。

从前往后推也是一样的,不过要维护一个最大值。

 

还有一个很严重的问题就是:30000×30000的空间太大了!

再深入分析,其实步长的变化范围没有3w那么大。

假设每一步步长为前面步长加一,可以求出最大步长。类似地,求出最小步长。

假设d=1,最大步长不会超过245 + d,因为技术分享

同样的,如果d≤244,则最小步长为0.

如果d≥245,技术分享

所以,最小步长不会小于max{0, d - 245}.

技术分享
 1 #include <cstdio>
 2 #include <algorithm>
 3 using namespace std;
 4 
 5 int max3(int a, int b, int c)
 6 { return max(max(a, b), c); }
 7 
 8 int w[70000], dp[65000][500];
 9 
10 int main()
11 {
12     //freopen("in.txt", "r", stdin);
13 
14     int n, d;
15     scanf("%d%d", &n, &d);
16     for(int i = 0; i < n; ++i)
17     {
18         int x;
19         scanf("%d", &x);
20         w[x]++;
21     }
22 
23     int maxp, minp = 1;
24     for(int n = 0; ; n++) if(d*(n+1)+n*(n+1)/2 >= 30000)
25     {
26         maxp = d + n;   //最大步长
27         break;
28     }
29     for(int n = 0; d >= 245; n++) if(d*(n+1)-n*(n+1)/2 >= 30000)
30     {
31         minp = d - n;   //最小步长
32         break;
33     }
34 
35     for(int x = 30000; x >= d; --x)
36         for(int l = minp; l <= maxp; ++l)
37             dp[x][l-minp+1] = w[x] + max3(dp[x+l][l-minp+1], dp[x+l+1][l+2-minp], dp[x+l-1][l-minp]);
38 
39     printf("%d\n", dp[d][d+1-minp]);
40 
41     return 0;
42 }
代码君

 

CodeForces Round #286 Div.2

标签:

原文地址:http://www.cnblogs.com/AOQNRMGYXLMV/p/4248074.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!