• 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
  • 相关阅读:
    分布式搜索elasticsearch 基本概念
    hdoj 4828 卡特兰数取模
    Tyvj3308毒药解药题解
    安全类工具制作第004篇:进程管理器(上)
    UVA
    G 全然背包
    指针结构体函数-事实上能够这样具体理解
    关于大型站点技术演进的思考(七)--存储的瓶颈(7)
    Testing Is the Engineering Rigor of Software Development
    poj 1273 Drainage Ditches(最大流)
  • 原文地址:https://www.cnblogs.com/shjwudp/p/4550639.html
Copyright © 2020-2023  润新知