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

    第2次CF,前半个小时发现前面3题都是水题,直接1A,第4题是求最短路,用BFS跑了一下,感觉题目的限制应该不会超时,交了以后也过了,第5题是关于随机排列的题目,模拟了交换最少次数,交了之后也过了,第6题是求图的连通分量,但是图很大,边是由两个数字的&性质决定的,用一个set,学会了边删除边遍历。由于一直在queue中,睡一觉后发现还是没过,但是值得庆幸的是我的其他5题没有被hack。所以排到了134名,感觉妥妥的,rateing飙升160,现在有1660蓝名,希望接下来到暑假可以冲击紫名。

    http://codeforces.com/contest/987

    A:太水略过

    B:求x^y 和y^x大小

    取对数,比赛的时候怕精度问题,用了eps判等于,结果过了。

     1 #include<bits/stdc++.h>
     2 using namespace std;
     3 typedef long long ll;
     4 int main()
     5 {
     6     double x, y, eps = 1e-12;
     7     cin >> x >> y;
     8     double ans = x * log(y) - y * log(x);
     9     if(fabs(ans) < eps)cout<<"="<<endl;
    10     else if(ans > 0) cout<<"<"<<endl;
    11     else cout<<">"<<endl;
    12     return 0;
    13 }

    C:给数组s和c,满足i<j<k 且 si < sj < sk 使ci + cj + ck最小

    直接DP,DP[i][j]为以i结尾长度为j的最大价值。最终求最小的DP[i][3]

    初始化DP[i][1] = s[i]

    注意,dp[i][2]中i从2开始递推,dp[i][3]中i从3开始递推,为了防止出错,写了两个二重循环。

     1 #include<bits/stdc++.h>
     2 using namespace std;
     3 typedef long long ll;
     4 const int maxn = 5000;
     5 const int INF = 1e9 + 7;
     6 ll a[maxn], b[maxn], dp[maxn][5];
     7 int main()
     8 {
     9     int n;
    10     cin >> n;
    11     for(int i = 1; i <= n; i++)cin >> a[i];
    12     for(int i = 1; i <= n; i++)cin >> b[i], dp[i][1] = b[i];
    13     for(int i = 2; i <= 3; i++)
    14         for(int j = 1; j <= n; j++)dp[j][i] = INF;
    15     ll ans = INF;
    16     for(int i = 2; i <= n; i++)
    17     {
    18         for(int j = 1; j < i; j++)
    19             if(a[j] < a[i])
    20             dp[i][2] = min(dp[i][2], dp[j][1] + b[i]);
    21     }
    22     for(int i = 3; i <= n; i++)
    23     {
    24         for(int j = 2; j < i; j++)
    25             if(a[j] < a[i])
    26             dp[i][3] = min(dp[i][3], dp[j][2] + b[i]);
    27     }
    28     for(int i = 1; i <= n; i++)ans = min(ans, dp[i][3]);
    29     if(ans == INF)cout<<"-1"<<endl;
    30     else cout<<ans<<endl;
    31     return 0;
    32 }

    D:n个城市,m条无向路,共有k种货物,每个城市只有一种货物,让你求在城市i举办交易会,至少有s种货物参加,求最少的路径之和

    由于s和k最大为100,可以用BFS跑每一个点,跑到货物种类等于s的时候返回路径和(这里是种类不是数量)

     1 #include<bits/stdc++.h>
     2 using namespace std;
     3 typedef long long ll;
     4 const int maxn = 100000 + 10;
     5 const int INF = 1e9 + 7;
     6 bool vis[maxn], v[maxn];
     7 int dis[maxn], a[maxn];
     8 vector<int>G[maxn];
     9 int n, m, k, S;
    10 int BFS(int s)
    11 {
    12     memset(vis, 0,sizeof(vis));
    13     memset(v, 0,sizeof(v));
    14     vis[s] = 1;
    15     dis[s] = 0;
    16     int tot = 0, now, ans = 0, u;
    17     queue<int>q;
    18     q.push(s);
    19     while(!q.empty())
    20     {
    21         now = q.front();
    22         q.pop();
    23         if(!v[a[now]])
    24         {
    25             v[a[now]] = 1;
    26             tot++;
    27             ans += dis[now];
    28             if(tot == S)return ans;
    29         }
    30         for(int i = 0; i < G[now].size(); i++)
    31         {
    32             u = G[now][i];
    33             if(!vis[u])
    34             {
    35                 vis[u] = 1;
    36                 dis[u] = dis[now] + 1;
    37                 q.push(u);
    38             }
    39         }
    40     }
    41 }
    42 int main()
    43 {
    44     scanf("%d%d%d%d", &n, &m, &k, &S);
    45     for(int i = 1; i <= n; i++)scanf("%d", &a[i]);
    46     int u, v;
    47     while(m--)
    48     {
    49         scanf("%d%d", &u, &v);
    50         G[u].push_back(v);
    51         G[v].push_back(u);
    52     }
    53     //BFS(1);
    54     printf("%d", BFS(1));
    55     for(int i = 2; i <= n; i++)printf(" %d", BFS(i));
    56     puts("");
    57     return 0;
    58 }

    E:给出一个1-n随机排列,Petr的随机化排列方法是随机交换3*n次,Um_nik的随机化排列方法是随机交换7*n+1次。问给出的排列是谁随机化得到的。

    初始排列 1,2,3...n

    模拟了一下最小交换次数tot,如果3*n -  tot是偶数的话,那么就是Petr的,否则就是Um_nik的

    数组a存储序列,数组b的b[i]表示a[j] = i的j的值

     1 #include<bits/stdc++.h>
     2 using namespace std;
     3 typedef long long ll;
     4 const int maxn = 1000000 + 10;
     5 const int INF = 1e9 + 7;
     6 int a[maxn], b[maxn];
     7 int main()
     8 {
     9     int n;
    10     cin >> n;
    11     for(int i = 1; i <= n; i++)
    12     {
    13         scanf("%d", &a[i]);
    14         b[a[i]] = i;
    15     }
    16     int tot = 0, u;
    17     for(int i = 1; i <= n; i++)
    18     {
    19         if(a[i] == i)continue;
    20         tot++;
    21         u = b[i];
    22         swap(b[i], b[a[i]]);
    23         swap(a[i], a[u]);
    24     }
    25     tot = 3 * n - tot;
    26     if(tot % 2 == 0)cout<<"Petr"<<endl;
    27     else cout<<"Um_nik"<<endl;
    28     return 0;
    29 }

    F:给n和m,还有m个互不相同的数,均小于1<<n,如果m个数字中a & b = 0,那么a 和b有边相连,问有多少个连通分量

    比赛的时候,用set存储每个数,每次取出第一个数,在set中删去与他相邻的点,重复,但是还是超时了,不过学到了如何用set边删除边遍历。

    对于迭代器it,如果需要删除it指向的位置

      先用it2 = it存下这个位置

      it++

      s.erase(it2)

    这样就可以遍历的时候删除了

    题目正解应该是,把每个数看做一个01集合,对于在m个数中的数,求它的补集的子集个数即可

    这里用4位来举个例子,

    比如5(0101),补集:(1010),补集的子集:(1010)  (1000) (0010) (0000)

    补集的子集和该集合的&运算的结果为0,满足条件。

    那么就可以枚举0 - ((1<<n) - 1)进行DFS即可。每次找到所有联通的点。

    时间复杂度O(1<<n)

     1 #include<bits/stdc++.h>
     2 using namespace std;
     3 typedef long long ll;
     4 const int maxn = (1<<23);
     5 bool vis[maxn], num[maxn];
     6 int n, m;
     7 void dfs(int x)
     8 {
     9     if(vis[x])return;
    10     vis[x] = 1;
    11     for(int i = 0; i < n; i++)//遍历x的子集
    12     {
    13         if(x & (1 << i))
    14             dfs(x ^ (1 << i));
    15     }
    16     if(num[x])dfs(((1<<n) - 1) & (~x));//如果是num中的元素,就寻找x的补集的子集
    17 }
    18 int main()
    19 {
    20     int x;
    21     scanf("%d%d", &n, &m);
    22     for(int i = 1; i <= m; i++)
    23     {
    24         scanf("%d", &x);
    25         num[x] = 1;
    26     }
    27     int ans = 0;
    28     for(int i = 0; i < (1 << n); i++)
    29     {
    30         if(num[i] && !vis[i])
    31             dfs(((1<<n) - 1) & (~i)), ans++;//dfs其补集
    32     }
    33     cout<<ans<<endl;
    34     return 0;
    35 }
  • 相关阅读:
    HDFS上传/下载数据的过程和原理
    使用JavaAPI获取文件信息
    jquery 最佳实践
    jQuery ajax
    两中复制表结构
    c#基础知识
    类和结构区别
    访问修饰符
    设计模式详细
    设计模式分类
  • 原文地址:https://www.cnblogs.com/fzl194/p/9112965.html
Copyright © 2011-2022 走看看