1. 程式人生 > >2016-2017 ACM-ICPC Pacific Northwest Regional Contest (Div. 1) Solution

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 }
View Code

 

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 }
View Code

 

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 }
View Code

 

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 }
View Code
 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 }
View Code

 

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 }
View Code

 

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 }
View Code

 

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 }
View Code

 

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 }
View Code

 

L:Windy Path

Unsolved.