zoukankan      html  css  js  c++  java
  • Codeforces Round #302 (Div. 2)

    A. Set of Strings

      题意:能否把一个字符串划分为n段,且每段第一个字母都不相同?

      思路:判断字符串中出现的字符种数,然后划分即可。

     1 #include<iostream>
     2 #include<set>
     3 #include<cstdio>
     4 #include<cstring>
     5 using namespace std;
     6 char s[110];
     7 set<char>st;
     8 int main()
     9 {
    10     int n;
    11     scanf("%d%s", &n,s);
    12     int len = strlen(s);
    13     for (int i = 0; i < len; i++)
    14     {
    15         if (!st.count(s[i]))st.insert(s[i]);
    16     }
    17     if (st.size() < n) printf("NO
    ");
    18     else
    19     {
    20         st.clear();
    21         printf("YES
    ");
    22         int cur = 0;
    23         while (n--)
    24         {
    25             st.insert(s[cur]);
    26             while (cur<len&&st.count(s[cur]))
    27             {
    28                 printf("%c", s[cur++]);
    29             }
    30             if (n == 0)
    31             {
    32                 while(cur<len) printf("%c", s[cur++]); 
    33             }
    34             printf("
    ");
    35         }
    36     }
    37     return 0;
    38 }
    View Code

    B. Sea and Islands

      题意:n*n的网格里都是水,现在需要填沙造出k个陆地,两两之间有边相邻的看成一片陆地。

      思路:讨论奇偶。

     1 #include<iostream>
     2 #include<cstdio>
     3 using namespace std;
     4 int main()
     5 {
     6     int n, k;
     7     scanf("%d%d", &n, &k);
     8     int maxs = n / 2 * n + n % 2 * (n + 1) / 2;
     9     if (k > maxs)printf("NO
    ");
    10     else
    11     {
    12         printf("YES
    ");
    13         for (int i = 0; i < n; i++)
    14         {
    15             int st;
    16             if (i % 2==0) st = 0;
    17             else st = 1;
    18             for (int j=0; j < n; j++)
    19             {
    20                 if ((j - st) % 2 == 0&&k>0) printf("L"),k--;
    21                 else printf("S");
    22             }
    23             printf("
    ");
    24         }
    25     }
    26     return 0;
    27 }
    View Code

    C. Writing Code

      题意:有n个程序员,现在需要合作完成m行的代码,要求最多只有b个bug,求总方案数?

      思路:dp[i][j][k]:表示前i个程序员一起写j行代码bug数为k的方案数.采用滚动数组优化。

     1 #include<iostream>
     2 #include<cstdio>
     3 using namespace std;
     4 const int maxn = 510;
     5 const int maxm = 510;
     6 const int maxb = 510;
     7 int dp[2][maxm][maxb];//[i][j][k]表示前i个程序员一起写j行代码bug数为k的方案数
     8 int bugs[maxn];
     9 int main()
    10 {
    11     int n, m, b, mod;
    12     scanf("%d%d%d%d", &n, &m, &b, &mod);
    13     for (int i = 1; i <= n; i++) scanf("%d", bugs + i);
    14     dp[0][0][0] = dp[1][0][0] = 1;
    15     int pre, now;
    16     for (int i = 1; i <= n; i++)
    17     {
    18         for (int j = 1; j <= m; j++)
    19         {
    20             for (int k =0; k <= b; k++)
    21             {
    22                 pre = ((i - 1) & 1),now=(i&1);
    23                 if (k >= bugs[i]) dp[now][j][k] = (dp[pre][j][k] + dp[now][j - 1][k - bugs[i]]) % mod;
    24                 else dp[now][j][k] = dp[pre][j][k];
    25             }
    26         }
    27     }
    28     int ans = 0;
    29     for (int i = 0; i <= b; i++) ans = (ans + dp[now][m][i]) % mod;
    30     printf("%d
    ",ans);
    31     return 0;
    32 }
    View Code

     D. Destroying Roads

      题意:有n个点,m条无向边。在保证s1到t1不超过l1小时、s2到t2不超过l2小时(每走一条边花费1小时)的情况下,求最多可以删去多少条边?

      思路:求出每两点之间的最短距离,然后2层循环枚举重复的路径。

     1 #include<iostream>
     2 #include<cstdio>
     3 #include<algorithm>
     4 #include<queue>
     5 #include<cstring>
     6 using namespace std;
     7 const int maxn = 3010;
     8 struct edge
     9 {
    10     int next, to;
    11     edge(int tt=0,int nn=0):to(tt),next(nn){}
    12 };
    13 edge Edge[maxn*maxn];
    14 int Head[maxn], totedge;
    15 void addedge(int from, int to)
    16 {
    17     Edge[totedge] = edge(to, Head[from]);
    18     Head[from] = totedge++;
    19     Edge[totedge] = edge(from, Head[to]);
    20     Head[to] = totedge++;
    21 }
    22 int dis[maxn][maxn];
    23 bool vis[maxn];
    24 const int INF = 0x3f3f3f3f;
    25 int n, m;
    26 void SPFA(int st)
    27 {
    28     for (int i = 0; i <= n; i++) dis[st][i] = INF;
    29     dis[st][st] = 0;
    30     vis[st] = true;
    31     queue<int>q;
    32     q.push(st);
    33     while (!q.empty())
    34     {
    35         int u = q.front();
    36         q.pop();
    37         vis[u] = false;
    38         for (int i = Head[u]; i != -1; i = Edge[i].next)
    39         {
    40             int v = Edge[i].to;
    41             if (dis[st][v] > dis[st][u] + 1)
    42             {
    43                 dis[st][v] = dis[st][u] + 1;
    44                 if (!vis[v])
    45                 {
    46                     vis[v] = true;
    47                     q.push(v);
    48                 }
    49             }
    50         }
    51     }
    52 }
    53 int main()
    54 {
    55     scanf("%d%d", &n, &m);
    56     memset(Head, -1, sizeof(Head));
    57     totedge = 0;
    58     for (int i = 1; i <= m; i++)
    59     {
    60         int u, v;
    61         scanf("%d%d", &u, &v);
    62         addedge(u, v);
    63     }
    64     int s1, d1, l1, s2, d2, l2;
    65     scanf("%d%d%d%d%d%d", &s1, &d1, &l1, &s2, &d2, &l2);
    66     for (int i = 1; i <= n; i++) SPFA(i);
    67     if (dis[s1][d1] > l1 || dis[s2][d2] > l2) printf("-1
    ");
    68     else
    69     {
    70         int minnum = dis[s1][d1] + dis[s2][d2];
    71         for (int i = 1; i <= n; i++)
    72         {
    73             for (int j = 1; j <= i; j++)
    74             {
    75                 if (dis[s1][i] + dis[i][j] + dis[j][d1] <= l1 && dis[s2][i] + dis[i][j] + dis[j][d2] <= l2)
    76                 {
    77                     minnum = min(minnum, dis[s1][i] + dis[i][j] + dis[j][d1] + dis[s2][i] + dis[j][d2]);
    78                 }
    79                 if (dis[s1][i] + dis[i][j] + dis[j][d1] <= l1 && dis[s2][j] + dis[j][i] + dis[i][d2] <= l2)
    80                 {
    81                     minnum = min(minnum, dis[s1][i] + dis[i][j] + dis[j][d1] + dis[s2][j] + dis[i][d2]);
    82                 }
    83                 if (dis[s1][j] + dis[j][i] + dis[i][d1] <= l1 && dis[s2][i] + dis[i][j] + dis[j][d2] <= l2)
    84                 {
    85                     minnum = min(minnum, dis[s1][j] + dis[j][i] + dis[i][d1] + dis[s2][i] + dis[j][d2]);
    86                 }
    87                 if (dis[s1][j] + dis[j][i] + dis[i][d1] <= l1 && dis[s2][j] + dis[j][i] + dis[i][d2] <= l2)
    88                 {
    89                     minnum = min(minnum, dis[s1][j] + dis[j][i] + dis[i][d1] + dis[s2][j] + dis[i][d2]);
    90                 }
    91             }
    92         }
    93         printf("%d
    ", m - minnum);
    94     }
    95     return 0;
    96 }
    View Code

     E. Remembering Strings

      题意:有n个字符串,每个字符串m位,要使得每个字符串存在一个位置i上的字符唯一(其他字符串该位上的字符与该字符串不同,称为易记字符串),你可以将某个字符串某位替换成任意字符,给出每个字符串每位替换的代价,求最小代价?

      思路:将n个字符串各自是否为易记标记为0/1,则我们可以进行状态压缩,对每个当前的状态,找到最低位的0(表示该字符串进行转换,其余高位的0无需转换),按照以下策略进行替换:如果该位唯一,则dp[i | (1 << j)] = dp[i],否则考虑2种方案:第一种方案,直接让该位字符唯一——dp[i | (1 << j)] = min(dp[i | (1 << j)], dp[i] + cost[j][k]);第二种方案,找到所有和该字符串该位字符一样的所有字符串,除去代价最大的,其他字符串进行转换——dp[i | tmp] = min(dp[i | tmp], dp[i] + sumc - maxc)。

      初始化为-1时需要考虑当前状态在此前是否已被转换到,没有则跳过;初始化为INF则不用考虑。

     1 #include<iostream>
     2 #include<algorithm>
     3 #include<cstdio>
     4 #include<cstring>
     5 using namespace std;
     6 char str[25][25];
     7 int cost[25][25];
     8 const int maxc = 1 << 20;//最大状态数
     9 int dp[maxc];
    10 int main()
    11 {
    12     int n, m;
    13     scanf("%d%d", &n, &m);
    14     for (int i = 0; i < n; i++) scanf("%s", str + i);
    15     for (int i = 0; i < n; i++)
    16     {
    17         for (int j = 0; j < m; j++) scanf("%d", &cost[i][j]);
    18     }
    19     int total = (1 << n) - 1;//最终状态为111...11,n个1表示n个字符串都为易记
    20     memset(dp, -1, sizeof(dp));
    21     dp[0] = 0;
    22     for (int i = 0; i <total; i++)//枚举状态
    23     {
    24         if (dp[i] == -1) continue;//该状态没有被转移到,跳过
    25         int j = 0;
    26         while (((i >> j) & 1) == 1) j++;//找到该状态中为非易记的字符串进行状态转移
    27         for (int k = 0; k < m; k++)
    28         {//让该字符串第k位的字符唯一
    29             int cnt = 0, sumc = 0, maxc = 0, tmp = 0;
    30             for (int z = 0; z < n; z++)
    31             {
    32                 if (str[z][k] == str[j][k])
    33                 {
    34                     cnt++;
    35                     sumc += cost[z][k];//总代价
    36                     maxc = max(maxc, cost[z][k]);//最大代价
    37                     tmp |= (1 << z);//所有和该字符串该位一样的字符串为易记时的状态
    38                 }
    39             }
    40             if (cnt == 1)//如果该位字符本就唯一
    41             {
    42                 if (dp[i | (1 << j)] == -1)dp[i | (1 << j)] = dp[i];
    43                 else dp[i | (1 << j)] = min(dp[i | (1 << j)], dp[i]);
    44             }
    45             else//否则
    46             {
    47                 //第一种方案,直接让该位字符唯一
    48                 if (dp[i | (1 << j)] == -1) dp[i | (1 << j)] = dp[i] + cost[j][k];
    49                 else dp[i | (1 << j)] = min(dp[i | (1 << j)], dp[i] + cost[j][k]);
    50                 //第二种方案,找到所有和该字符串该位字符一样的所有字符串,除去代价最大的,其他字符串进行转换
    51                 if (dp[i | tmp] == -1) dp[i | tmp] = dp[i] + sumc - maxc;
    52                 else dp[i | tmp] = min(dp[i | tmp], dp[i] + sumc - maxc);
    53             }
    54         }
    55     }
    56     printf("%d
    ", dp[total]);
    57     return 0;
    58 }
    View Code
  • 相关阅读:
    CLR Via CSharp读书笔记(26)
    RH253读书笔记(10)-Appendix A Installing Software
    RH253读书笔记(9)-Lab 9 Account Management Methods
    一位程序员工作10年总结的13个忠告
    不跟你谈“五险一金”的老板,都是在耍流氓
    RH253读书笔记(8)-Lab 8 Securing Data
    RH253读书笔记(7)-Lab 7 Electronic Mail
    RH253读书笔记(6)-Lab 6 Implementing Web(HTTP) Services
    robotium测试创建java文件和junit文件区别
    LigerUi中为Grid表加上序号,并调整适当宽度!(实例)
  • 原文地址:https://www.cnblogs.com/ivan-count/p/8727657.html
Copyright © 2011-2022 走看看