Codeforces Round #302 (Div. 2) 题解

题目链接:http://codeforces.com/contest/544

A、题意:给你k和一个串,要你在把串分成k部分,且首字母都不相同

解:直接看串有没有k种不同字母

 1 /*
 2  * Problem:  
 3  * Author:  SHJWUDP
 4  * Created Time:  2015/6/3 星期三 13:20:56
 5  * File Name: 233.cpp
 6  * State: 
 7  * Memo: 
 8  */
 9 #include <iostream>
10 #include <cstdio>
11 #include <cstring>
12 #include <algorithm>
13 
14 using namespace std;
15 
16 const int MaxA=100+7;
17 
18 int k;
19 char str[MaxA];
20 bool vis[26];
21 int stk[MaxA], top;
22 int main() {
23 #ifndef ONLINE_JUDGE
24     freopen("in", "r", stdin);
25     //freopen("out", "w", stdout);
26 #endif
27     while(~scanf("%d%s", &k, str)) {
28         memset(vis, 0, sizeof(vis));
29         top=0;
30         for(int i=0; str[i] && k; i++) {
31             if(vis[str[i]-'a']==0) {
32                 k--;
33                 vis[str[i]-'a']++;
34                 stk[++top]=i;
35             }
36         }
37         if(k<=0) {
38             printf("YES
");
39             int pos=0;
40             stk[++top]=strlen(str);
41             for(int i=2; i<=top; i++) {
42                 while(pos<stk[i]) putchar(str[pos++]);
43                 putchar('
');
44             }
45         } else {
46             printf("NO
");
47         }
48     }
49     return 0;
50 }
View Code

B、题意:给你一个n*n的沙盘,你可以令任意一个单元是沙子或者是海水,问你可不可以做出k个不相邻的岛屿(沙子区域)

解:简单构造,尽可能多的分割沙子即可(沙子海水交错放置)

 1 /*
 2  * Problem:  
 3  * Author:  SHJWUDP
 4  * Created Time:  2015/6/3 星期三 13:20:56
 5  * File Name: 233.cpp
 6  * State: 
 7  * Memo: 
 8  */
 9 #include <iostream>
10 #include <cstdio>
11 #include <cstring>
12 #include <algorithm>
13 
14 using namespace std;
15 
16 const int MaxA=100+7;
17 
18 int n, k;
19 int main() {
20 #ifndef ONLINE_JUDGE
21     freopen("in", "r", stdin);
22     //freopen("out", "w", stdout);
23 #endif
24     while(~scanf("%d%d", &n, &k)) {
25         int num=0;
26         if(n&1) {
27             int tmp=(n>>1)+1;
28             num=tmp*tmp+(tmp-1)*(tmp-1);
29         } else {
30             int tmp=n>>1;
31             num=tmp*n;
32         }
33         if(num<k) printf("NO
");
34         else {
35             printf("YES
");
36             for(int i=0; i<n; i++) {
37                 for(int j=0; j<n; j++) {
38                     if(!k) {
39                         printf("S");
40                         continue;
41                     }
42                     if((i&1)==(j&1)) {
43                         k--; printf("L");
44                     } else printf("S");
45                 }
46                 printf("
");
47             }
48         }
49     }
50     return 0;
51 }
View Code

C、题意:有n个coder,每个人有属性vi,表示第i个coder每敲一行代码会出现vi个bug,现在要让这n个coder完成一个m行代码的任务,且bug总数少于b,问有多少分配任务的方式(每人只能分配非负整数行代码,答案对mod取模)

解:dp,f[i][j]表示 在敲了i行代码且有j个bug的状态时 的分配方式数

 1 /*
 2  * Problem:  
 3  * Author:  SHJWUDP
 4  * Created Time:  2015/6/3 星期三 18:19:15
 5  * File Name: 233.cpp
 6  * State: 
 7  * Memo: 
 8  */
 9 #include <iostream>
10 #include <cstdio>
11 #include <cstring>
12 #include <algorithm>
13 
14 using namespace std;
15 
16 const int MaxA=500+7;
17 
18 int n, m, b, mod;
19 int arr[MaxA];
20 int f[MaxA][MaxA];
21 int main() {
22 #ifndef ONLINE_JUDGE
23     freopen("in", "r", stdin);
24     //freopen("out", "w", stdout);
25 #endif
26     while(~scanf("%d%d%d%d", &n, &m, &b, &mod)) {
27         for(int i=0; i<n; i++) {
28             scanf("%d", &arr[i]);
29         }
30         memset(f, 0, sizeof(f));
31         f[0][0]=1;
32         for(int i=0; i<n; i++) {
33             for(int j=1; j<=m; j++) {
34                 for(int k=arr[i]; k<=b; k++) {
35                     f[j][k]=(f[j][k]+f[j-1][k-arr[i]])%mod;
36                 }
37             }
38         }
39         int ans=0;
40         for(int i=0; i<=b; i++) {
41             ans=(ans+f[m][i])%mod;
42         }
43         printf("%d
", ans);
44     }
45     return 0;
46 }
View Code

D、题意:给你一张n个点,m条边的无向图,任意相邻点的边权为1,再给你s1,t1,l1,s2,t2,l2,要在满足s1到t1的最短路不大于l1,s2到t2的最短路不大于l2的情况下,尽可能多地删边

解:考虑只有s1,t1,l1限制的情况,ans=m-(s1到t1的最短路),那么我们只要求出s1,t1最短路与s2,t2最短路的最小并集即可

求出任意两点的最短路径,然后枚举两点作为两条最短路径的相交部分,求解(注意,有可能两条最短路径不相交更优)

 1 /*
 2  * Problem:  
 3  * Author:  SHJWUDP
 4  * Created Time:  2015/6/3 星期三 18:19:15
 5  * File Name: 233.cpp
 6  * State: 
 7  * Memo: 
 8  */
 9 #include <iostream>
10 #include <cstdio>
11 #include <cstring>
12 #include <algorithm>
13 #include <queue>
14 
15 using namespace std;
16 
17 const int INF=0x3f3f3f3f;
18 
19 const int MaxA=3e3+7;
20 
21 struct Edge {
22     int v, nt;
23     Edge(){}
24     Edge(int v, int nt):v(v), nt(nt){}
25 } edges[MaxA<<1];
26 
27 int head[MaxA], edgeNum;
28 
29 int n, m;
30 int dis[MaxA][MaxA];
31 void init() {
32     edgeNum=0;
33     memset(head, -1, sizeof(head));
34 }
35 void addEdge(int u, int v) {
36     edges[edgeNum]=Edge(v, head[u]);
37     head[u]=edgeNum++;
38 }
39 void bfs(int s) {
40     int *d=dis[s];
41     memset(dis[s], 0x3f, sizeof(dis[s]));
42     d[s]=0;
43     queue<int> Q;
44     Q.push(s);
45     while(!Q.empty()) {
46         int u=Q.front(); Q.pop();
47         for(int i=head[u]; ~i; i=edges[i].nt) {
48             Edge& e=edges[i];
49             if(d[e.v]==INF) {
50                 d[e.v]=d[u]+1;
51                 Q.push(e.v);
52             }
53         }
54     }
55 }
56 int main() {
57 #ifndef ONLINE_JUDGE
58     freopen("in", "r", stdin);
59     //freopen("out", "w", stdout);
60 #endif
61     while(~scanf("%d%d", &n, &m)) {
62         init();
63         for(int i=0; i<m; i++) {
64             int a, b;
65             scanf("%d%d", &a, &b);
66             addEdge(a, b);
67             addEdge(b, a);
68         }
69         int s1, t1, s2, t2, l1, l2;
70         scanf("%d%d%d", &s1, &t1, &l1);
71         scanf("%d%d%d", &s2, &t2, &l2);
72         for(int i=1; i<=n; i++) {
73             bfs(i);
74         }
75         if(dis[s1][t1]>l1 || dis[s2][t2]>l2) {
76             puts("-1");
77             continue;
78         }
79         int ans=dis[s1][t1]+dis[s2][t2];
80         for(int i=1; i<=n; i++) {
81             for(int j=1; j<=n; j++) {
82                 int w1=min(dis[s1][i]+dis[i][j]+dis[j][t1], 
83                         dis[s1][j]+dis[j][i]+dis[i][t1]);
84                 int w2=min(dis[s2][i]+dis[i][j]+dis[j][t2], 
85                         dis[s2][j]+dis[j][i]+dis[i][t2]);
86                 if(w1>l1 || w2>l2) continue;
87                 ans=min(ans, w1+w2-dis[i][j]);
88             }
89         }
90         printf("%d
", m-ans);
91     }
92     return 0;
93 }
View Code

 E、题意:给你n个长度为m的串和转换任意一个字符的代价,要你花费最小代价使这个串集的每一个串至少有一个字符与该字符所在列的其他字符不同

解:状压表示已经处理的串,状态扩展:对于一个新的串,枚举每个字符,那么要么更换这个字符,要么更换该列的其他字符

 1 /*
 2  * Problem:  
 3  * Author:  SHJWUDP
 4  * Created Time:  2015/6/4 星期四 10:21:49
 5  * File Name: 233.cpp
 6  * State: 
 7  * Memo: 
 8  */
 9 #include <iostream>
10 #include <cstdio>
11 #include <cstring>
12 #include <algorithm>
13 
14 using namespace std;
15 
16 const int INF=0x3f3f3f3f;
17 
18 const int MaxA=20+7;
19 
20 int n, m;
21 char str[MaxA][MaxA];
22 int arr[MaxA][MaxA];
23 int f[1<<20];
24 int lowzero(int x) {
25     int res=0;
26     while(x&1) {
27         x>>=1; res++;
28     }
29     return res;
30 }
31 int main() {
32 #ifndef ONLINE_JUDGE
33     freopen("in", "r", stdin);
34     //freopen("out", "w", stdout);
35 #endif
36     while(~scanf("%d%d", &n, &m)) {
37         for(int i=0; i<n; i++) {
38             scanf("%s", str[i]);
39         }
40         for(int i=0; i<n; i++) {
41             for(int j=0; j<m; j++) {
42                 scanf("%d", &arr[i][j]);
43             }
44         }
45         memset(f, 0x3f, sizeof(f)); f[0]=0;
46         int staNum=1<<n;
47         for(int s=0; s<staNum; s++) {
48             if(f[s]==INF) continue;
49             int r=lowzero(s); 
50             if(r>=n) continue;
51             for(int j=0; j<m; j++) {
52                 f[s|(1<<r)]=min(f[s|(1<<r)], f[s]+arr[r][j]);
53                 int bits=0, sum=0, mx=0;
54                 for(int i=0; i<n; i++) if(str[i][j]==str[r][j]) {
55                     sum+=arr[i][j];
56                     mx=max(mx, arr[i][j]);
57                     bits|=1<<i;
58                 }
59                 f[s|bits]=min(f[s|bits], f[s]+sum-mx);
60             }
61         }
62         printf("%d
", f[staNum-1]);
63     }
64     return 0;
65 }
View Code
原文地址:https://www.cnblogs.com/shjwudp/p/4550639.html