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

    链接:

    http://codeforces.com/contest/543

    过程:

    惨淡的只做出了A和C

    题解:

    A

    题解:

    简单的一道题

    我们用$dp[i][j]$表示当前考虑到前num个人(这个另外枚举),当前写了$i$行代码,当前的bug数量为$j$的方案数

    然后转移就是$dp[i][j]=sum {dp[i-1][j-a[num]]}$

    Code:

     1 #include<stdio.h>
     2 #include<cstring>
     3 #include<cstdlib>
     4 #include<algorithm>
     5 #include<vector>
     6 #include<map>
     7 #include<set>
     8 #include<cmath>
     9 #include<iostream>
    10 #include<queue>
    11 #include<string>
    12 using namespace std;
    13 typedef long long ll;
    14 typedef pair<int,int> pii;
    15 typedef long double ld;
    16 typedef unsigned long long ull;
    17 typedef pair<long long,long long> pll;
    18 #define fi first
    19 #define se second
    20 #define pb push_back
    21 #define mp make_pair
    22 #define rep(i,j,k)  for(register int i=(int)(j);i<=(int)(k);i++)
    23 #define rrep(i,j,k) for(register int i=(int)(j);i>=(int)(k);i--)
    24 
    25 ll read(){
    26     ll x=0,f=1;char c=getchar();
    27     while(c<'0' || c>'9'){if(c=='-')f=-1;c=getchar();}
    28     while(c>='0' && c<='9'){x=x*10+c-'0';c=getchar();}
    29     return x*f;
    30 }
    31 
    32 const int MAXN = 510;
    33 
    34 int mod;
    35 int a[MAXN];
    36 int dp[MAXN][MAXN];
    37 
    38 int add(int a, int b)
    39 {
    40     return (a + b) % mod;
    41 }
    42 
    43 int main()
    44 {
    45     int n, m, b;
    46     cin >> n >> m >> b >> mod;
    47     for (int i = 0; i < n; i++)
    48         cin >> a[i];
    49     dp[0][0] = 1;
    50     for (int i = 0; i < n; i++)
    51         for (int j = 1; j <= m; j++)
    52             for (int k = a[i]; k <= b; k++)
    53                 dp[j][k] = add(dp[j][k], dp[j - 1][k - a[i]]);
    54     int ans = 0;
    55     for (int i = 0; i <= b; i++)x
    56         ans = add(ans, dp[m][i]);
    57     cout << ans << endl;
    58 }
    View Code

    Review:

    比较容易的一道题

    B

    题解:

    首先可以通过BFS得到dis[i][j]数组,也就是任意两点的最短路

    然后分两种情况

    1. 只剩下s1到t1,s2到t2的最短路 代价:m-dis[s1][t1]-dis[s2][t2]

    2. 剩下的两条路径有交,组成一个‘H’形状

    代价:枚举i,j表示那个交集的两端

    然后剩下的边数的可能情况就是dis[s1][i]+dis[s2][i]+dis[i][j]+dis[j][t1]+dis[j][t2] 或者 dis[s1][i]+dis[t2][i]+dis[i][j]+dis[j][t1]+dis[j][s2]

    取一个最小值 再用m减去就好了

    注意判断这样的i,j不满足l1,l2的要求的情况

    Code:

      1 #include<stdio.h>
      2 #include<cstring>
      3 #include<cstdlib>
      4 #include<algorithm>
      5 #include<vector>
      6 #include<map>
      7 #include<set>
      8 #include<cmath>
      9 #include<iostream>
     10 #include<queue>
     11 #include<string>
     12 using namespace std;
     13 typedef long long ll;
     14 typedef pair<int,int> pii;
     15 typedef long double ld;
     16 typedef unsigned long long ull;
     17 typedef pair<long long,long long> pll;
     18 #define fi first
     19 #define se second
     20 #define pb push_back
     21 #define mp make_pair
     22 #define rep(i,j,k)  for(register int i=(int)(j);i<=(int)(k);i++)
     23 #define rrep(i,j,k) for(register int i=(int)(j);i>=(int)(k);i--)
     24 
     25 ll read(){
     26     ll x=0,f=1;char c=getchar();
     27     while(c<'0' || c>'9'){if(c=='-')f=-1;c=getchar();}
     28     while(c>='0' && c<='9'){x=x*10+c-'0';c=getchar();}
     29     return x*f;
     30 }
     31 
     32 const int maxn=3030;
     33 int n,m;
     34 vector<int> gr[maxn];
     35 int dis[maxn][maxn];
     36 bool vis[maxn];
     37 
     38 void bfs(int u){
     39     queue<int> q;
     40     while(!q.empty()) q.pop();
     41     memset(vis,0,sizeof(vis));
     42     vis[u]=1;q.push(u);
     43     while(!q.empty()){
     44         int v=q.front();
     45         q.pop();
     46         for(int i=0;i<gr[v].size();i++){
     47             int nw=gr[v][i];
     48             if(vis[nw]) continue;
     49             vis[nw]=1;
     50             dis[u][nw]=dis[u][v]+1;
     51             q.push(nw);
     52         }
     53     }
     54 }
     55 
     56 int main(){
     57     n=read(),m=read();
     58     rep(i,1,m){
     59         int a=read(),b=read();
     60         gr[a].pb(b),gr[b].pb(a);
     61     }
     62     int s1,t1,l1,s2,t2,l2;
     63     s1=read(),t1=read(),l1=read();
     64     s2=read(),t2=read(),l2=read();
     65     
     66     rep(i,1,n){
     67         bfs(i);
     68     }
     69     
     70     if(dis[s1][t1]>l1 || dis[s2][t2]>l2){
     71         puts("-1");
     72         return 0;
     73     }
     74     int ans1=m-dis[s1][t1]-dis[s2][t2];
     75     int ans2=0;
     76     for(int i=1;i<=n;i++){
     77         for(int j=1;j<=n;j++){
     78             if(i==j) continue;
     79             int nw=dis[s1][i]+dis[s2][i]+dis[i][j]+dis[j][t1]+dis[j][t2];
     80             if(dis[s1][i]+dis[i][j]+dis[j][t1]>l1 || dis[s2][i]+dis[i][j]+dis[j][t2]>l2) nw=1e9;
     81             int nw2=dis[s1][i]+dis[t2][i]+dis[i][j]+dis[j][t1]+dis[j][s2];
     82             if(dis[s1][i]+dis[i][j]+dis[j][t1]>l1 || dis[t2][i]+dis[i][j]+dis[j][s2]>l2) nw2=1e9;
     83             ans2=max(ans2,max(m-nw,m-nw2));
     84         }
     85     }
     86     printf("%d
    ",max(ans1,ans2));
     87     return 0;
     88 }
     89 
     90 /*
     91 9 9
     92 1 2
     93 2 3
     94 2 4
     95 4 5
     96 5 7
     97 5 6
     98 3 8
     99 8 9
    100 9 6
    101 1 7 4
    102 3 6 3
    103 */
    View Code

    Review:

    我竟然连能够求出dis数组都没看出来

    傻傻的以为要floyd或者n遍dijkstra

    没注意到边权为1。。。

    所以边权为1----BFS

    C

    题解:

    很显然要用状压dp

    (毕竟20的数据范围摆在那里)

    那么令$dp[mask]$表示将mask对应的字符串变成easy to remember的最小代价

    复杂度最多只能为$O(2^n imes n)$ 所以还可以枚举一层

    那么怎么做呢

    考虑转移:

    首先我们不能做到O(1)转移

    所以不能枚举每一个属于mask的字符串

    那么我们必须做到对于任意一个属于mask的字符串 通过我们的转移都能够得到答案

    所以必须得有两种转移

    我们令选取的字符串为$s_i$,剩下的状态为$nwmask$

    1. 把$s_i$改动一位,并压进去

    因为最多20个字符串而有26个字母,所以可以保证改任意一位都可行

    那肯定选择最少的代价的那一位去修改

    2. 改动其他的字符串的某一位,使得他们和$s_i$的这一位都不同

    这个代价是可以预处理的

    Code:

     1 #include <bits/stdc++.h>
     2 
     3 #define forn(i, n) for(int i = 0; i < int(n); i++)
     4 
     5 using namespace std;
     6 
     7 const int N = 20;
     8 const int leng = 300;
     9 string s[N];
    10 int cost[N][leng], c[N][leng], sv[N][leng], a[N][leng];
    11 int d[1 << N];
    12 
    13 int main() {
    14   int n, m;
    15   cin >> n >> m;
    16   forn(i, n) cin >> s[i];
    17   forn(i, n) forn(j, m) cin >> a[i][j];
    18   
    19   forn(i, n) {
    20     forn(j, m) {
    21       int curv = 0;
    22       forn(k, n) {
    23         if (s[i][j] == s[k][j]) {
    24           sv[i][j] |= (1 << k);
    25           c[i][j] += a[k][j];
    26           curv = max(curv, a[k][j]);
    27         }
    28       }
    29       c[i][j] -= curv;
    30     }
    31   }
    32   forn(i, 1 << n) d[i] = 1000000000;
    33   d[0] = 0;
    34   forn(mask, 1 << n) {
    35     if (mask == 0) continue;
    36     int lowbit = -1;
    37     forn(i, n) {
    38       if ((mask >> i) & 1) {
    39         lowbit = i;
    40         break;
    41       }
    42     }
    43     forn(i, m) {
    44       d[mask] = min(d[mask], d[mask & (mask ^ sv[lowbit][i])] + c[lowbit][i]);
    45       d[mask] = min(d[mask], d[mask ^ (1 << lowbit)] + a[lowbit][i]);
    46     }
    47   }
    48   printf("%d
    ", d[(1 << n) - 1]);
    49   return 0;
    50 }
    View Code

    Review:

    我觉得挺难的,但是怎么那么多人随手切啊

    D

    题解:

    首先如果只要算1为根的答案是个很简单的树形dp

    用$dp[i]$表示以i为根的子树的答案

    $dp[i]=prod {(dp[son]+1)}$

    然后我们考虑怎么算每个点的答案

    我们通过父亲的答案求儿子的答案

    怎么做呢?

    首先我们看从父亲到儿子有哪些变化

    我们用ans[i]记录i结点对应的上方给i的贡献 然后再乘上dp[i](i的下方对i的贡献)就是i为根的答案

    我们怎么计算ans数组呢

    发现从父亲到儿子的变化就在于多了几个儿子对应的兄弟

    $ans[son]=ans[father] imes prod {(dp[brother]+1)}$

    所以我们记录L,R表示当前结点的儿子们的前缀(dp+1)的积,后缀(dp+1)的积

    然后$ans[son]=ans[father]*L[son]*R[son]*ans[father]+1$就可以了

    +1指的是把儿子的父亲当作儿子的儿子的时候计算答案的时候要把dp+1相乘

    Code:

     1 #include<stdio.h>
     2 #include<cstring>
     3 #include<cstdlib>
     4 #include<algorithm>
     5 #include<vector>
     6 #include<map>
     7 #include<set>
     8 #include<cmath>
     9 #include<iostream>
    10 #include<queue>
    11 #include<string>
    12 using namespace std;
    13 typedef long long ll;
    14 typedef pair<int,int> pii;
    15 typedef long double ld;
    16 typedef unsigned long long ull;
    17 typedef pair<long long,long long> pll;
    18 #define fi first
    19 #define se second
    20 #define pb push_back
    21 #define mp make_pair
    22 #define rep(i,j,k)  for(register int i=(int)(j);i<=(int)(k);i++)
    23 #define rrep(i,j,k) for(register int i=(int)(j);i>=(int)(k);i--)
    24 
    25 ll read(){
    26     ll x=0,f=1;char c=getchar();
    27     while(c<'0' || c>'9'){if(c=='-')f=-1;c=getchar();}
    28     while(c>='0' && c<='9'){x=x*10+c-'0';c=getchar();}
    29     return x*f;
    30 }
    31 
    32 const int mod=1000000007;
    33 int n;
    34 vector<int> adj[200200];
    35 ll dp[200200],L[200200],R[200200];
    36 ll ans[200200];
    37 
    38 void dfs(int x){
    39     dp[x]=1;
    40     for(int i=0;i<adj[x].size();i++){
    41         int v=adj[x][i];
    42         dfs(v);
    43         dp[x]=dp[x]*(dp[v]+1)%mod;
    44     }
    45 }
    46 
    47 void dfs2(int x){
    48     int num=adj[x].size();
    49     if(num==0) return;
    50     L[0]=1,R[num-1]=ans[x];
    51     for(int i=0;i<adj[x].size();i++){
    52         int v=adj[x][i];
    53         L[i+1]=L[i]*(dp[v]+1)%mod;
    54     }
    55     for(int i=num-1;i>=0;i--){
    56         int v=adj[x][i];
    57         R[i-1]=R[i]*(dp[v]+1)%mod;
    58     }
    59     for(int i=0;i<num;i++){
    60         int v=adj[x][i];
    61         ans[v]=(L[i]*R[i]+1)%mod;
    62     }
    63     for(int i=0;i<num;i++){
    64         int v=adj[x][i];
    65         dfs2(v);
    66     }
    67 }
    68 
    69 int main(){
    70     n=read();
    71     rep(i,2,n){
    72         int x=read();
    73         adj[x].pb(i);
    74     }
    75     dfs(1);
    76     ans[1]=1;
    77     dfs2(1);
    78     rep(i,1,n)
    79         printf("%lld ",dp[i]*ans[i]%mod);
    80     puts("");
    81     return 0;
    82 }
    83 
    84 /*
    85 5
    86 1 2 3 4
    87 */
    View Code

    Review:

    第一个dp很好想

    但是怎么求ans不知道怎么想的

    可能需要灵机一动

  • 相关阅读:
    vs 编译加速
    leetcode 1405
    sort 从大到小从小到大
    leetcode1404
    leetcode 1406
    leetcode 1556
    杭电研究生自动登录联网脚本
    Cannot mix incompatible Qt library (version ) with this library (version ) 解决方案
    目标检测算法优化技巧
    特征工程和模型融合--机器学习--思维导图和笔记
  • 原文地址:https://www.cnblogs.com/wawawa8/p/9490481.html
Copyright © 2011-2022 走看看