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\n",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 \times 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\n", d[(1 << n) - 1]);
49   return 0;
50 }
View Code

Review:

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

猜你喜欢

转载自www.cnblogs.com/wawawa8/p/9490481.html