zoukankan      html  css  js  c++  java
  • 20140705 总结

    说好的的赛区难度... →_→ “不完全是赛区难度”==“完全不是赛区难度”

    看完了题做好了爆0的准备,从testC开始写,结果有30,正解是dp...

    testB我是在最后十分钟才写的,感觉像最长公共子序列,但是时间不够了,我就直接printf("%d ", s/e);结果有80...

    testA写了个Floyd,然后就开始乱搞了,结果就wa0...

     -----------------------------------------------------------------------------

    testA

    输入文件: testA.in  输出文件: testA.out 时限: 2000ms

     

    问题描述:

             有一个城市拥有N个节点,被M条有权无向路径连接。现在你要在一个地方(可以在路径上当然也可以在节点上)开设一家咖啡馆,使得所有节点达到这个咖啡馆的最短路里面最大值最小(也就是说离咖啡馆最远的节点距离尽可能得小),求出这个最大值的最小值。

     

    输入描述:

    第一行N和M。

    第2至M+1行,每行三个整数U,V,W。表示从U到V有一条权值为W的无向边。

     

    输出描述:

    一行一个数表示答案。 四舍五入至2位小数

    数据范围 N<=200 , W<=100000 , M<=19900

     

    样例输入:

    3 2
    1 2 100
    2 3 1

     

    样例输出:

    50.50

     

    题解:

    二分答案L

    对于一个L,枚举每一条边(x, y, w),只要有一条边符合情况,L合法

    对于一条边,枚举每一个点k:(1)dis[x][k]>L && dis[y][k]>L ->这条边不和发

                   l = L-dis[x][k], r = L-dis[y][k]

                  (2) l>=w || r>=w || r+l>=w ->这个点对于这条边合法

                  (3) 求一个区间, 既对于点k在这条直线上标出不合法的安放区间

                                            -> 求并集U:

                         若U==[0,w]->此边不合法

                       else ->合法   

     1 #define NOMBRE "testA"
     2 #include <cstdio>
     3 #include <vector>
     4 #include <cstring>
     5 #include <algorithm>
     6 using namespace std;
     7 
     8 const int INF = 0x3f3f3f3f;
     9 const int MAXN = 200+10;
    10 
    11 double Pri;
    12 int N, M, dis[MAXN][MAXN];
    13 
    14 struct Edge{
    15     int to, d;
    16 };
    17 
    18 vector< pair<int, int> > cj;
    19 vector<Edge> e[MAXN];
    20 
    21 inline Edge MakeEdge(int to, int d){
    22     Edge ret;
    23     ret.to = to, ret.d = d;
    24     return ret;
    25 }
    26 
    27 inline void Floyd(){
    28     for (int i=1; i<=N; i++)
    29         dis[i][i] = 0;
    30     for (int k=1; k<=N; k++)
    31         for (int i=1; i<=N; i++){
    32             if (dis[i][k]==INF) continue;
    33             for (int j=1; j<=N; j++)
    34                 dis[i][j] = min(dis[i][j], dis[i][k]+dis[k][j]);
    35 
    36         }
    37 }
    38 
    39 inline bool OkayEdge(int L, int x, int y, int w){
    40     int dl, dr, Tail = 0, CJs;
    41     cj.clear();
    42     for (int k=1; k<=N; k++){
    43         dl = L-dis[x][k], dr = L-dis[y][k];
    44         if (dl<0 && dr<0) return false;
    45         if (dl>=w || dr>=w || dl+dr>=w) continue;
    46         cj.push_back(make_pair(dl+1, w-dr-1));
    47     }
    48     if (cj.empty()) return true;
    49     sort(cj.begin(), cj.end());
    50     CJs = cj.size();
    51     for (int i=0; i<CJs; i++){
    52         if (Tail<cj[i].first) return true;
    53         if (Tail<cj[i].second+1) Tail = cj[i].second+1;
    54     }
    55     return false;
    56 }
    57 
    58 inline bool Okay(int L){
    59     int Es;
    60     for (int i=1; i<=N; i++){
    61         Es = e[i].size();
    62         for (int j=0; j<Es; j++)
    63             if (OkayEdge(L, i, e[i][j].to, e[i][j].d)) return true;
    64     }
    65     return false;
    66 }
    67 
    68 int main(){
    69     freopen(NOMBRE ".in", "r", stdin);
    70     freopen(NOMBRE ".out", "w", stdout);
    71 
    72     memset(dis, 0x3f, sizeof(dis));
    73     scanf("%d %d", &N, &M);
    74     int u, v, d;
    75     for (int i=0; i<M; i++)
    76         scanf("%d %d %d", &u, &v, &d),
    77         d <<= 1, e[u].push_back(MakeEdge(v, d)),
    78         dis[u][v] = dis[v][u] = min(dis[u][v], d);
    79     Floyd();
    80     int l = 0, r = INF, Mid;
    81     while (l<=r){
    82         Mid = (l+r)>>1;
    83         if (Okay(Mid)) r = Mid-1, Pri = Mid;
    84         else l = Mid+1;
    85     }
    86     printf("%.2lf", Pri/=2.0);
    87 }

     

     -----------------------------------------------------------------------------

    testB

    输入文件: testB.in  输出文件testB.out 时限2000ms

     

    问题描述:

    方师傅有两个由数字组成的串 a1,a2,⋯,an 和 b1,b2,⋯,bm。 有一天,方师傅感到十分

    无聊因此他决定用这两个串来玩玩游戏。游戏规则十分简单,方师傅会进行一些操作,每个操作可能是以下两种操作之一:

     

    1.从a串选择一个a的非空前缀,再从b串选一个b的非空前缀。这两个前缀的最后一个元素必须相等,完成选择后把这两个前缀删除。

     

    2.删除两个串所有的元素。

     

    第一种操作会耗费e的能量值,并为方师傅增加一美分到他的电子账户中。第二种操作会耗费两个串的不完整度的能量。不完整度 = 两个串已经被删除的元素的数目。只有执行第二种操作后,方师傅才能从电子帐户中取出他的钱。 

    刚开始时,方师傅有一个空的电子账户和s的能量,请问方师傅最多可以赚多少美分?注意,由于乐警官偷吃光了方师傅的士力架,导致方师傅无法补充能量,因此方师傅的能量任何时候都不能小于0。

     

    输入描述: 

    第一行4个整数,n,m,s,e(1≤n,m≤10^5;1≤s≤3×10^5;10^3≤e≤10^4)。

    第二行n个整数,a1,a2⋯an.

    第三行m个整数,b1,b2⋯bm.

    1≤ai,bi≤10^5

     

    输出描述:

    输出一个整数,方师傅可以最多赚得的美分数目。

     

    样例输入1:

    5 5 100000 1000

    1 2 3 4 5

    3 2 4 5 1

     

    样例输出1:

    3
     

    样例输入2:

    3 4 3006 1000
    1 2 3
    1 2 4 3

     

    样例输出2:

    2

     

    dp[i][j]表示A匹配到i位置获得j美分是匹配到B的位置

     //看来标程才想到vector...多么美好vector啊

     1 #define NOMBRE "testB"
     2 #include <vector>
     3 #include <cstdio>
     4 #include <cstring>
     5 #include <algorithm>
     6 using namespace std;
     7 
     8 const int MAXN = 1e5+10;
     9 const int MAXJ = 300+10;
    10 
    11 int n, m, s, e, x, Best, Pri, a[MAXN], b[MAXN], dp[MAXN][MAXJ];
    12 vector<int> v[MAXN];
    13 
    14 int main(){
    15     freopen(NOMBRE ".in", "r", stdin);
    16     freopen(NOMBRE ".out", "w", stdout);
    17 
    18     memset(dp, 0x3f, sizeof(dp));
    19     scanf("%d %d %d %d", &n, &m, &s, &e), Best = s/e;
    20     for (int i=1; i<=n; i++)
    21         scanf("%d", &a[i]);
    22     for (int i=1; i<=m; i++)
    23         scanf("%d", &b[i]),
    24         v[b[i]].push_back(i);
    25     
    26     int temp;
    27     dp[0][0] = 0;
    28     for (int i=1; i<=n; i++){
    29         dp[i][0] = 0;
    30         for (int j=0; j<=Best; j++){
    31             dp[i][j] = dp[i-1][j];
    32             x = upper_bound(v[a[i]].begin(), v[a[i]].end(), dp[i-1][j-1])-v[a[i]].begin();
    33             temp = v[a[i]].size();
    34             if (x<temp) dp[i][j] = min(dp[i][j], v[a[i]][x]);
    35             if (j>Pri && i+dp[i][j]+j*e<=s) Pri = j; 
    36         }
    37     }    
    38     printf("%d
    ", Pri);
    39 }

     

    -----------------------------------------------------------------------------

    testC 

    输入文件: testC.in  输出文件testC.out 时限1000ms 

     

    问题描述:

    给你一组数,a1, a2a3,⋯,an。令:G=gcd(a1, a2a3,⋯,an)。

    现在从中任意删除一些数字,设剩下的数为:a1, a2a3,⋯,am。再令:g=gcd(a1, a2a3,⋯,am)

    现要求G=g,问最多能删除多少数?

     

    输入描述:

    第一行一个数n,第二行n个数a1,a2,a3,⋯,an

    1≤n≤700

    1≤ai≤10000

     

    输出描述:

    输出只有一个数,表示最多能删除多少数。

     

    样例输入:

    3
    4 6 8

    样例输出

    1

     

    题解:

    dp[i]表示使得gcd为i最少使用多少数

     1 #define NOMBRE "testc"
     2 #include <cstdio>
     3 #include <cstring>
     4 #include <algorithm>
     5 using namespace std;
     6 
     7 const int N = 10000; 
     8 const int MAXN = 700+10;
     9 
    10 int n, g, dp[N+10], a[MAXN], max;
    11 
    12 int gcd(int a, int b){
    13     if (!a && b) return b;
    14     if (!b && a) return a;
    15     while (b^=a^=b^=a%=b);
    16     return a;
    17 }
    18 
    19 int main(){
    20     freopen(NOMBRE ".in", "r", stdin);
    21     freopen(NOMBRE ".out", "w", stdout);
    22 
    23     memset(dp, 0x3f, sizeof(dp));
    24     scanf("%d", &n), dp[0] = Max = g = 0;
    25     for (int i=0; i<n; i++)
    26         scanf("%d", &a[i]), g = gcd(g, a[i]), Max = max(Max, a[i]);
    27     for (int i=0; i<n; i++)
    28         for (int j=0; j<=Max; j++)
    29             dp[gcd(a[i], j)] = min(dp[gcd(a[i], j)], dp[j]+1);
    30     printf("%d
    ", n-dp[g]);
    31 }

     

  • 相关阅读:
    (七) rest_framework GenericAPIView/GenericViewSet/ ModelViewSet 解析
    (六) rest_framework 普通分页与加密分页
    (五) rest_framework 序列化与解析器源码实现
    (四) rest_framework 版本控制源码
    【使用 PySpark 分析 CSV 文件】
    安装 HBase1.3.6 on Windows 10 64 bit
    Spark Job 性能调优 (二)
    Spark RDD 分区到底怎么用?
    安装 Spyder python 开发环境 用于 Spark 数据分析 -word count
    安装 Spark on Windows 使用 PySpark
  • 原文地址:https://www.cnblogs.com/cjhahaha/p/3827026.html
Copyright © 2011-2022 走看看