2016-2017 ACM-ICPC Pacific Northwest Regional Contest (Div. 1) Solution

A:Alphabet

Solved.

签。

 1 #include<bits/stdc++.h>
 2 using namespace std;
 3 char s[60];
 4 int f[60];
 5 int main(){
 6     scanf("%s",s+1);
 7     int n=strlen(s+1);
 8     for(int i=1;i<=n;i++)
 9     {
10         f[i]=1;
11     }
12     for(int i=2;i<=n;i++)
13     {
14         for(int j=1;j<i;j++)
15         {
16             if(s[i]>s[j]){
17                 f[i]=max(f[i],f[j]+1);
18             }
19         }
20     }
21     int maxn=0;
22     for(int i=1;i<=n;i++)
23     {
24         maxn=max(maxn,f[i]);
25     }
26     cout<<26-maxn<<endl;
27 }

B:Buggy Robot

Solved.

题意:

给出一个地图,从‘R‘ 走到 ‘E‘ , 可以增加或者删除机器人的指令

求最少的修改次数,使得机器人可以到达‘E‘

思路:

搜索。

  1 #include<bits/stdc++.h>
  2
  3 using namespace std;
  4
  5 const int maxn = 50 + 10;
  6 const int INF = 0x3f3f3f3f;
  7
  8 struct node{
  9     int x, y;
 10     int step;
 11     node(){}
 12     node(int x, int y, int step): x(x), y(y), step(step){};
 13 };
 14
 15 int n, m;
 16 int sx, sy, ex, ey;
 17 int len;
 18 char mp[maxn][maxn];
 19 char op[maxn * maxn];
 20 int dis[maxn][maxn][maxn * maxn];
 21 int dir[4][2] = {1, 0, 0, 1, -1, 0, 0, -1};
 22
 23 bool judge(int x,int y)
 24 {
 25     if(x < 1 || x > n || y < 1 || y > m || mp[x][y] == ‘#‘) return false;
 26     else return true;
 27 }
 28
 29 void BFS()
 30 {
 31     queue<node>q;
 32     q.push(node(sx, sy, 0));
 33     dis[sx][sy][0] = 0;
 34     while(!q.empty())
 35     {
 36         node st = q.front();
 37         q.pop();
 38         //not do
 39         if(st.step + 1 <= len)
 40         {
 41             node now = st;
 42             now.step++;
 43             if(dis[st.x][st.y][st.step] + 1 < dis[now.x][now.y][now.step])
 44             {
 45                 dis[now.x][now.y][now.step] = dis[st.x][st.y][st.step] + 1;
 46                 q.push(now);
 47             }
 48         }
 49         //do
 50         if(st.step + 1 <= len)
 51         {
 52             node now = st;
 53             now.step++;
 54             if(op[now.step] == ‘U‘)
 55             {
 56                 now.x--;
 57             }
 58             else if(op[now.step] == ‘D‘)
 59             {
 60                 now.x++;
 61             }
 62             else if(op[now.step] == ‘L‘)
 63             {
 64                 now.y--;
 65             }
 66             else if(op[now.step] == ‘R‘)
 67             {
 68                 now.y++;
 69             }
 70             if(!judge(now.x, now.y))
 71             {
 72                 now.x = st.x;
 73                 now.y = st.y;
 74             }
 75             if(dis[st.x][st.y][st.step] < dis[now.x][now.y][now.step])
 76             {
 77                 dis[now.x][now.y][now.step] = dis[st.x][st.y][st.step];
 78                 q.push(now);
 79             }
 80
 81         }
 82         //add
 83         node now = st;
 84         for(int i = 0; i < 4; ++i)
 85         {
 86             now.x = st.x + dir[i][0];
 87             now.y = st.y + dir[i][1];
 88             if(judge(now.x, now.y))
 89             {
 90                 if(dis[st.x][st.y][st.step] + 1 < dis[now.x][now.y][now.step])
 91                 {
 92                     dis[now.x][now.y][now.step] = dis[st.x][st.y][st.step] + 1;
 93                     q.push(now);
 94                 }
 95             }
 96         }
 97     }
 98 }
 99
100 int main()
101 {
102     while(~scanf("%d %d", &n, &m))
103     {
104         for(int i = 1; i <= n; ++i)
105         {
106             for(int j = 1; j <= m; ++j)
107             {
108                 scanf(" %c", &mp[i][j]);
109                 if(mp[i][j] == ‘R‘){ sx = i, sy = j; }
110                 if(mp[i][j] == ‘E‘){ ex = i, ey = j; }
111             }
112         }
113         scanf("%s", op + 1);
114         len = strlen(op + 1);
115         memset(dis, 0x3f, sizeof dis);
116         BFS();
117         int ans = INF;
118         for(int i = 1; i <= len; ++i) ans = min(ans, dis[ex][ey][i]);
119         printf("%d\n", ans);
120     }
121     return 0;
122 }

C:Cameras

Solved.

签。

 1 #include <bits/stdc++.h>
 2 using namespace std;
 3
 4 #define N 100010
 5 int n, k, r, a[N];
 6
 7 int main()
 8 {
 9     while (scanf("%d%d%d", &n, &k, &r) != EOF)
10     {
11         memset(a, 0, sizeof a);
12         for (int i = 1, x; i <= k; ++i)
13         {
14             scanf("%d", &x);
15             a[x] = 1;
16         }
17         int res = 0;
18         int tot = 0;
19         for (int i = 1; i <= r - 1; ++i) tot += a[i];
20         for (int i = 1; i + r - 1<= n; ++i)
21         {
22             tot += a[i + r - 1];
23             if (tot < 2)
24             {
25                 for (int j = i + r - 1; j >= 1 && tot < 2; --j) if (!a[j])
26                 {
27                     a[j] = 1;
28                     ++tot;
29                     ++res;
30                 }
31             }
32             tot -= a[i];
33         }
34         printf("%d\n", res);
35     }
36     return 0;
37 }

D:Contest Strategy

Unsolved.

题意:

在一场ICPC比赛中,有一个人知道它解决每道题需要多少时间

但是必须要先读这道题,才能做

做题策略是

开场先随机读k道题,然后按做题时间放入小根堆

每次取堆顶出来做,每做一道题,就随机再读一题(如果还有题目可以读)

求$\;N!\;种读题顺序的所有罚时加起来 MOD\;\; 1e\;9 +7$

E:Enclosure

Unsolved.

F:Illumination

Solved.

题意:

有一个矩形,在某些点有灯泡,可以选择照亮当前行或者照亮当前列

每个灯泡照亮的范围相同为$r$

但是同行或者同列的照亮不能相交

求有没有一种方案使得所有灯泡都可以打开

思路:

一个点拆成两个点,表示照亮行或列

然后建边,丢进2-sat跑一跑即可

 1 #include<bits/stdc++.h>
 2 using namespace std;
 3
 4 #define N 2010
 5 int n, r, l;
 6 struct Graph
 7 {
 8     struct node
 9     {
10         int to, nx;
11         node () {}
12         node (int to, int nx) : to(to), nx(nx) {}
13     }a[N * N * 2];
14     int head[N], pos;
15     void init()
16     {
17         memset(head, -1, sizeof head);
18         pos = 0;
19     }
20     void add(int u, int v) { a[++pos] = node(v, head[u]); head[u] = pos; }
21 }G;
22 #define erp(u) for (int it = G.head[u], v = G.a[it].to; ~it; it = G.a[it].nx, v = G.a[it].to)
23 int x[N], y[N];
24 // 0 x 1 y
25
26 bool vis[N];
27 int S[N], top;
28 bool DFS(int u)
29 {
30     if (vis[u ^ 1]) return false;
31     if (vis[u]) return true;
32     vis[u] = 1;
33     S[top++] = u;
34     erp (u) if (!DFS(v)) return false;
35     return true;
36 }
37
38 bool twosat(int n)
39 {
40     memset(vis, 0, sizeof vis);
41     for (int i = 0; i < n; i += 2)
42     {
43         if (vis[i] || vis[i ^ 1]) continue;
44         top = 0;
45         if (!DFS(i))
46         {
47             while (top) vis[S[--top]] = false;
48             if (!DFS(i ^ 1)) return false;
49         }
50     }
51     return true;
52 }
53
54 int main()
55 {
56     while (scanf("%d%d%d", &n, &r, &l) != EOF)
57     {
58         G.init();
59         for (int i = 0; i < l; ++i) scanf("%d%d", x + i, y + i);
60         for (int i = 0; i < l; ++i) for (int j = i + 1; j < l; ++j)
61         {
62             if (x[i] == x[j] && abs(y[i] - y[j]) <= 2 * r)
63             {
64                 G.add(i << 1, j << 1 | 1);
65                 G.add(j << 1, i << 1 | 1);
66             }
67             if (y[i] == y[j] && abs(x[i] - x[j]) <= 2 * r)
68             {
69                 G.add(i << 1 | 1, j << 1);
70                 G.add(j << 1 | 1, i << 1);
71             }
72         }
73         puts(twosat(2 * l) ? "YES" : "NO");
74     }
75     return 0;
76 }

 1 #include<bits/stdc++.h>
 2
 3 using namespace std;
 4
 5 const int maxn = 2e3 + 10;
 6
 7 struct node{
 8     int x, y;
 9     node(){}
10     node(int x,int y): x(x), y(y){}
11 }arr[maxn];
12
13 struct Edge{
14     int to, nxt;
15     Edge(){}
16     Edge(int to, int nxt) : to(to), nxt(nxt){}
17 }edge[(maxn * maxn) << 2];
18
19 int head[maxn << 1], tot, vis[maxn << 1];
20
21 void Init()
22 {
23     tot = 0;
24     memset(head, -1, sizeof head);
25     memset(vis, 0, sizeof vis);
26 }
27
28 void addedge(int u, int v, int val)
29 {
30     int tmpu = u * 2 + val;
31     int tmpv = v * 2 + val;
32     edge[tot] = Edge(tmpv, head[tmpu ^ 1]); head[tmpu ^ 1] = tot++;
33     edge[tot] = Edge(tmpu, head[tmpv ^ 1]); head[tmpv ^ 1] = tot++;
34 }
35
36 int n, r, l;
37 int S[maxn << 1], top;
38
39 bool DFS(int u)
40 {
41     if(vis[u ^ 1]) return false;
42     if(vis[u]) return true;
43     vis[u]++;
44     S[top++] = u;
45     for(int i = head[u]; ~i; i = edge[i].nxt)
46     {
47         if(!DFS(edge[i].to)) return false;
48     }
49     return true;
50 }
51
52 bool solve()
53 {
54     for(int i = 0; i < (l << 1); i += 2)
55     {
56         if(vis[i] == 0 && vis[i ^ 1] == 0)
57         {
58             top = 0;
59             if(!DFS(i))
60             {
61                 while(top) vis[S[--top]] = 0;
62                 if(!DFS(i ^ 1)) return false;
63             }
64         }
65     }
66     return true;
67
68 }
69
70 int main()
71 {
72     while(~scanf("%d %d %d", &n, &r, &l))
73     {
74         Init();
75         for(int i = 0; i < l; ++i) scanf("%d %d", &arr[i].x, &arr[i].y);
76         for(int i = 0; i < l; ++i)
77         {
78             for(int j = 0; j < i; ++j)
79             {
80                 if(arr[i].y == arr[j].y && abs(arr[i].x - arr[j].x) <= 2 * r)
81                 {
82                     addedge(i, j, 0);
83                 }
84                 if(arr[i].x == arr[j].x && abs(arr[i].y - arr[j].y) <= 2 * r)
85                 {
86                     addedge(i, j, 1);
87                 }
88             }
89         }
90         puts(solve() ? "YES" : "NO");
91     }
92     return 0;
93 }

G:Maximum Islands

Unsolved.

题意:

有一张卫星图,可以看到陆地上有些地方是海洋,有些地方是陆地

陆地的连通块是岛屿,也有些地方看到的是云朵

云朵下面可以是陆地也可以是海洋

求岛屿的最大数量

H:Paint

Solved.

题意:

给出一些区间,求选出任意个数的区间,使得这些区间不相交

并且区间并最大,输出n - 区间并

思路:
类似于最长上升子序列,一个区间的左端点要接在所有右端点小于它的所有区间中的最大值即可

树状数组维护一下就没了

 1 #include <bits/stdc++.h>
 2 using namespace std;
 3
 4 #define ll long long
 5 #define N 200010
 6 ll n, b[N << 2];
 7 int k, m;
 8 struct qnode
 9 {
10     ll l, r;
11     void scan() { scanf("%lld%lld", &l, &r); }
12     bool operator < (const qnode &other) const { return r < other.r || r == other.r && l < other.l; }
13 }q[N];
14
15 void Hash()
16 {
17     m = 0;
18     for (int i = 1; i <= k; ++i)
19     {
20         b[++m] = q[i].l;
21         b[++m] = q[i].r;
22     }
23     sort(b + 1, b + 1 + m);
24     m = unique(b + 1, b + 1 + m) - b - 1;
25     for (int i = 1; i <= k; ++i)
26     {
27         q[i].l = lower_bound(b + 1, b + 1 + m, q[i].l) - b;
28         q[i].r = lower_bound(b + 1, b + 1 + m, q[i].r) - b;
29     }
30 }
31
32 namespace BIT
33 {
34     ll a[N << 2];
35     void update(int x, ll val)
36     {
37         for (; x < (N << 2); x += x & -x)
38             a[x] = max(a[x], val);
39     }
40     ll query(int x)
41     {
42         ll res = 0;
43         for (; x; x -=x & -x)
44             res = max(res, a[x]);
45         return res;
46     }
47 }
48
49 int main()
50 {
51     while (scanf("%lld%d", &n, &k) != EOF)
52     {
53         for (int i = 1; i <= k; ++i) q[i].scan(); Hash();
54         sort(q + 1, q + 1 + k);
55         ll res = 0;
56         for (int i = 1; i <= k; ++i)
57         {
58             ll tmp = BIT::query(q[i].l - 1);
59             tmp += b[q[i].r] - b[q[i].l] + 1;
60             res = max(res, tmp);
61             BIT::update(q[i].r, tmp);
62         }
63         printf("%lld\n", n - res);
64     }
65     return 0;
66 }

I:Postman

Solved.

题意:

有n个房子,每个放在位于$x_i点$邮局在0点,每个房子有$m_i封信要送$

只有一个邮递员,每次最多携带$k_i封信,求邮递员最少的路程$

思路:

负的和正的分开做

每次都先跑最远的,如果可以携带多余的信,就给次远的,再给次次远的。

贪心做一下就没了

 1 #include <bits/stdc++.h>
 2 using namespace std;
 3
 4 #define ll long long
 5 #define N 1010
 6 ll res;
 7 int n, m, k;
 8 int x[N], v[N];
 9
10 struct node
11 {
12     int x, v;
13     node () {}
14     node (int x, int v) : x(x), v(v) {}
15     bool operator < (const node &r) const { return x < r.x; }
16 }q[N];
17
18 void solve()
19 {
20     sort(q + 1, q + 1 + m);
21     for (int i = m; i >= 1; --i)
22     {
23         res += 2ll * (q[i].v / k) * q[i].x;
24         int remind = q[i].v % k;
25         if (remind)
26         {
27             remind = k - remind;
28             res += 2ll * q[i].x;
29             for (int j = i - 1; j >= 1; --j)
30             {
31                 if (remind >= q[j].v)
32                 {
33                     remind -= q[j].v;
34                     q[j].v = 0;
35                 }
36                 else
37                 {
38                     q[j].v -= remind;
39                     break;
40                 }
41             }
42         }
43     }
44 }
45
46 int main()
47 {
48     while (scanf("%d%d", &n, &k) != EOF)
49     {
50         for (int i = 1; i <= n; ++i) scanf("%d%d", x + i, v + i);
51         res = 0; m = 0;
52         for (int i = 1; i <= n; ++i) if (x[i] < 0) q[++m] = node(-x[i], v[i]);
53         solve();
54         m = 0;
55         for (int i = 1; i <= n; ++i) if (x[i] > 0) q[++m] = node(x[i], v[i]);
56         solve();
57         printf("%lld\n", res);
58     }
59     return 0;
60 }

j:Shopping

Solved.

题意:

有一个超市,$有n种物品,每种物品a_i元,每种物品无限个$

$q次询问,每次询问从第l_i个商品走到第r_i个商品,身上有v_i块钱,能买则买,问最后剩下多少钱$

思路:

每次购买一个物品那么手中的钱至少缩小一半

最多需要购买log种物品

再二分查找最近的小于自己的物品

 1 #include <bits/stdc++.h>
 2 using namespace std;
 3
 4 #define ll long long
 5 #define N 200010
 6 int n, q;
 7 ll a[N];
 8
 9 ll dp[N][20];
10 int mm[N];
11 void init(int n, ll b[])
12 {
13     mm[0] = -1;
14     for (int i = 1; i <= n; ++i)
15     {
16         mm[i] = ((i & (i - 1)) == 0) ? mm[i - 1] + 1: mm[i - 1];
17         dp[i][0] = b[i];
18     }
19     for (int j = 1; j <= mm[n]; ++j)
20         for (int i = 1; i + (1 << j) - 1 <= n; ++i)
21             dp[i][j] = min(dp[i][j - 1], dp[i + (1 << (j - 1))][j - 1]);
22 }
23
24 ll query(int l, int r)
25 {
26     int k = mm[r - l + 1];
27     return min(dp[l][k], dp[r - (1 << k) + 1][k]);
28 }
29
30 int main()
31 {
32     while (scanf("%d%d", &n, &q) != EOF)
33     {
34         for (int i = 1; i <= n; ++i) scanf("%lld", a + i); init(n, a);
35         ll v;
36         for (int i = 1, l, r; i <= q; ++i)
37         {
38             scanf("%lld%d%d", &v, &l, &r);
39             while (r - l >= 0)
40             {
41                 int ql = l, qr = r, tar = -1;
42                 while (qr - ql >= 0)
43                 {
44                     int mid = (ql + qr) >> 1;
45                     if (query(ql, mid) <= v)
46                     {
47                         qr = mid - 1;
48                         tar = mid;
49                     }
50                     else
51                         ql = mid + 1;
52                 }
53                 if (tar == -1) break;
54                 v %= a[tar];
55                 l = tar + 1;
56             }
57             printf("%lld\n", v);
58         }
59     }
60     return 0;
61 }

K:Tournament Wins

Solved.

题意:

有$2^k个玩家,进行对局,rank小的一定能打败\;\;rank\;\;大的$

如果你$rank = r 那么求出你在一轮游戏中赢的局数的期望$

一轮游戏为每次两两对战,输的离开,赢得剩下继续对战,直到只有一个人

思路:

 1 #include<bits/stdc++.h>
 2 using namespace std;
 3
 4 const int maxn = (1 << 20) + 10;
 5 const double EXP = exp(1.0);
 6
 7 double fac[maxn];
 8
 9 void Init()
10 {
11     fac[0] = 0;
12     for(int i = 1; i < maxn; ++i) fac[i] = fac[i - 1] + log(i);
13 }
14
15 int k, r;
16
17 int main()
18 {
19     Init();
20     while(~scanf("%d %d", &k, &r))
21     {
22         double ans = 0;
23         int limit = 1 << k;
24         for(int i = 1; i <= k; ++i)
25         {
26             int m = (1 << i);
27             if(limit - r - m + 1 < 0) break;
28             ans += exp((fac[limit - r] - fac[limit - r -  m + 1]) - (fac[limit - 1] - fac[limit - m]));
29         }
30         printf("%.5f\n", ans);
31     }
32     return 0;
33 }

L:Windy Path

Unsolved.

原文地址:https://www.cnblogs.com/Dup4/p/10092503.html

时间: 2024-10-29 13:31:29

2016-2017 ACM-ICPC Pacific Northwest Regional Contest (Div. 1) Solution的相关文章

2018-2019 ACM-ICPC Pacific Northwest Regional Contest (Div. 1) Solution

A:Exam Solved. 温暖的签. 1 #include<bits/stdc++.h> 2 3 using namespace std; 4 5 const int maxn = 1e3 + 10; 6 7 int k; 8 char str1[maxn], str2[maxn]; 9 10 int main() 11 { 12 while(~scanf("%d",&k)) 13 { 14 scanf("%s", str1 + 1); 15

2017-2018 ACM-ICPC Pacific Northwest Regional Contest (Div. 2) P-Fear Factoring 区间内数的所有因数的和

题意就是标题. 思路: 对于每个数 a 算出 1~a 的所有因数和sum(a),输出sum(b)-sum(a-1). 关键在于如何求出 sum. 首先发现因数∈ 1 ≤ i ≤ n ,每个因数在区间[1,n]内的出现次数(不考虑4=2*2这样因数重复出现,这种情况2只算出现一次)等于 n/i (向下取整). 然后用 t = n/(n/i) 可以找到与因数i出现次数相同的最大因数(这里可能有点难理解,例如1~100区间内21作为因数出现的数字有 21 ,42 ,63 ,84:即四次.按计算机整数相

Gym - 101615J Grid Coloring DP 2017-2018 ACM-ICPC Pacific Northwest Regional Contest (Div. 1)

题目传送门 题目大意: 给出n*m的网格,有红蓝两种颜色,每个格子都必须被染色,当一个格子被染成蓝色后,这个格子左上方的一块都必须被染成蓝色,问最后的方案数量. 思路: 按照题目条件,如果有一个格子被染成了红色,则这个格子的右下方要全部被染成红色,也就是这个给出的网格能让我们染色的,是一个左上方和右下方都是阶梯型的图形,而对于每一行来说,当一个格子被染成了蓝色,那么左边的所有格子都必须被染成蓝色,所以我们设 f[ i ][ j ] 表示第 i 行 第 j 个格子被染成蓝色的方案数量,那么这个dp

2018-2019 ACM-ICPC Pacific Northwest Regional Contest (Div. 1) E,F

E 题意: 一个起点,可以将火车点割掉,问最小的代价使得起点不能到达边界. 思路: 拆点,火车点的入边到出边流量是割掉的价格,其他都是INF.最小割就是答案 #include<bits/stdc++.h> #define ll long long using namespace std; const int N = 45; const int M = N*N*2; const int INF = 0x3f3f3f3f; int n,m,k; struct node{ int x,y; }; s

ACM ICPC Central Europe Regional Contest 2013 Jagiellonian University Krak&#243;w

ACM ICPC Central Europe Regional Contest 2013 Jagiellonian University Kraków Problem A: Rubik's RectangleProblem B: What does the fox say?Problem C: Magical GCDProblem D: SubwayProblem E: EscapeProblem F: DraughtsProblem G: History courseProblem H: C

2013-2014 ACM-ICPC Pacific Northwest Regional Contest L.Languages

题意略. 思路: 这种字符串的模拟题,应该熟练使用stringstream. 详见代码: #include<bits/stdc++.h> using namespace std; map<string,string> mp; vector<string> store; void change(string& str){ for(int i = 0;i < str.length();++i){ str[i] = tolower(str[i]); } } in

2013-2014 ACM-ICPC Pacific Northwest Regional Contest D.Delta Quadrant

题意略. 思路: 由于这是一颗无根树,我们可以贪心地来删去边. 详见代码: #include<bits/stdc++.h> using namespace std; typedef long long LL; const int maxn = 1e4 + 5; struct edge{ int from,to,len,id; edge(int a = 0,int b = 0,int c = 0,int d = 0){ from = a,to = b,len = c,id = d; } bool

hdu6206 Apple 2017 ACM/ICPC Asia Regional Qingdao Online

地址:http://acm.split.hdu.edu.cn/showproblem.php?pid=6206 题目: Apple Time Limit: 1000/1000 MS (Java/Others)    Memory Limit: 65535/32768 K (Java/Others)Total Submission(s): 530    Accepted Submission(s): 172 Problem Description Apple is Taotao's favouri

2017 ACM/ICPC Asia Regional Shenyang Online spfa+最长路

transaction transaction transaction Time Limit: 4000/2000 MS (Java/Others)    Memory Limit: 132768/132768 K (Java/Others)Total Submission(s): 1496    Accepted Submission(s): 723 Problem Description Kelukin is a businessman. Every day, he travels arou