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

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

testB我是在最后十分钟才写的,感觉像最长公共子序列,但是时间不够了,我就直接printf("%d\n", 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\n", 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", n-dp[g]);
31 }

 

Posted on 2014-07-06 13:53  cjhahaha  阅读(340)  评论(0编辑  收藏  举报