2015-2016 ACM-ICPC Pacific Northwest Regional Contest (Div. 2)

A:
英语阅读题,没读懂题意,这个题出的严重很差,有兴趣的能够作一下,从后往前求便可;node

B:
题让你求每一步操做以后能mess up的数字(1-100)。每一步操做多是加减乘除,mess up的定义是出现负数或者小数。
按照题意进行模拟就好了,注意坑点:mess up的数字不会再次进行操做。(好比4 -> 4/3 -> 4/3*3这种状况)ios

 1 #include <bits/stdc++.h>
 2 using namespace std;
 3 #define rep(i,a,b) for(int i = a;i <= b;++ i)
 4 #define per(i,a,b) for(int i = a;i >= b;-- i)
 5 #define mem(a,b) memset((a),(b),sizeof((a)))
 6 #define FIN freopen("in.txt","r",stdin)
 7 #define IO ios_base::sync_with_stdio(0),cin.tie(0)
 8 #define pb push_back
 9 typedef long long LL;
10 typedef pair<int, int> PIR;
11 const int N = 1e6+5;
12 
13 int n;
14 bool vis[1005];
15 double a[N], x[N];
16 string op[N];
17 
18 int main()
19 {
20     cin >> n;
21     rep(i, 1, n)    cin >> op[i] >> x[i];
22     rep(i, 1, 100)  a[i] = i;
23     mem(vis, false);
24     int ans = 0;
25     rep(i, 1, 100){
26         rep(j, 1, n){
27             int res = a[i];
28             if(a[i] < 0 || res*1.0 != a[i]) continue;
29             if(op[j][0] == 'A')    a[i] += x[j];
30             if(op[j][0] == 'S')    a[i] -= x[j];
31             if(op[j][0] == 'M')    a[i] *= x[j];
32             if(op[j][0] == 'D')    a[i] = a[i]*1.0/x[j];
33         }
34         //cout << "a[i]: " << a[i] << endl;
35         int res = a[i];
36         if(a[i] < 0 || res*1.0 != a[i]) { vis[i] = true; ans++; }
37     }
38     cout << ans << endl;
39     return 0;
40 }
View Code


C:
按照题意说求最低的可让鸡蛋破碎的楼层ans1, 和不能破碎的最高楼层 ans2;
并且告诉你全部 <= safe都是安全的,全部 >= broken的都是不安全的。那么按照题意找出 max[safe] 和 min[broken];
答案 ans1 = max[safe]+1; ans2 = min[broken]-1;c++

 1 #include <bits/stdc++.h>
 2 using namespace std;
 3 #define rep(i,a,b) for(int i = a;i <= b;++ i)
 4 #define per(i,a,b) for(int i = a;i >= b;-- i)
 5 #define mem(a,b) memset((a),(b),sizeof((a)))
 6 #define FIN freopen("in.txt","r",stdin)
 7 #define IO ios_base::sync_with_stdio(0),cin.tie(0)
 8 #define pb push_back
 9 typedef long long LL;
10 typedef pair<int, int> PIR;
11 const int N = 1e6+5;
12 
13 int n, k, x, vis[N];
14 string s;
15 
16 int main()
17 {
18     cin >> n >> k;
19     int ans1 = k, ans2 = 1;
20     rep(i, 1, n){
21         cin >> x >> s;
22         if(s[0] == 'S') ans2 = max(ans2, x);
23         else ans1 = min(ans1, x);
24     }
25     //cout << "ans1: " << ans1 << " ans2: " << ans2 << endl;
26     cout << ans2+1 << " " << ans1-1 << endl;
27     return 0;
28 }
View Code

 

D:
一个 n*m 的方格,每一个格子都有权值k,每一步能够上下左右四个方向走k步;求左上到右下的最少步数;
简单bfs问题,一步变成k步就好;算法

 1 #include <bits/stdc++.h>
 2 using namespace std;
 3 #define rep(i,a,b) for(int i = a;i <= b;++ i)
 4 #define per(i,a,b) for(int i = a;i >= b;-- i)
 5 #define mem(a,b) memset((a),(b),sizeof((a)))
 6 #define FIN freopen("in.txt","r",stdin)
 7 #define IO ios_base::sync_with_stdio(0),cin.tie(0)
 8 #define pb push_back
 9 typedef long long LL;
10 typedef pair<int, int> PIR;
11 const int N = 505;
12 
13 int n, m, G[N][N], dir[4][2] = {0,1,0,-1,1,0,-1,0};
14 string s;
15 bool vis[N][N];
16 struct Node{
17     int x, y, cnt, len;
18     Node(int _x, int _y, int _len, int _cnt){
19         x = _x; y = _y; len = _len; cnt = _cnt;
20     }
21 };
22 bool judge(int x, int y){
23     if(x < 1 || x > n || y < 1 || y > m || vis[x][y])   return false;
24     return true;
25 }
26 void bfs(){
27     queue <Node> Q;
28     mem(vis, false);
29     Q.push(Node(1, 1, G[1][1], 0));
30     vis[1][1] = true;
31     while(!Q.empty()){
32         Node h = Q.front();
33         Q.pop();
34         int xx = h.x, yy = h.y, lenn = h.len, cntt = h.cnt;
35         if(xx == n && yy == m){
36             cout << cntt << endl;
37             return ;
38         }
39         rep(i, 0, 3){
40             int xi = xx+dir[i][0]*lenn, yi = yy+dir[i][1]*lenn;
41             if(judge(xi, yi)){
42                 vis[xi][yi] = true;
43                 Q.push(Node(xi, yi, G[xi][yi], cntt+1));
44             }
45         }
46     }
47     cout << "IMPOSSIBLE" << endl;
48     return ;
49 }
50 int main()
51 {IO;
52     //FIN;
53     while(cin >> n >> m){
54         rep(i, 1, n){
55             cin >> s;
56             rep(j, 0, m-1)  G[i][j+1] = (s[j]-'0');
57         }
58         bfs();
59     }
60     return 0;
61 }
View Code

 

E:
给定一个字符串,只含有小写字母,让你求最少删除多少个字符以后,这个字符串的不一样字符个数 <= 2;
用个数组下标表明字符,而后求个数+sort,结果就是把前24个加起来。数组

 1 #include <bits/stdc++.h>
 2 using namespace std;
 3 #define rep(i,a,b) for(int i = a;i <= b;++ i)
 4 #define per(i,a,b) for(int i = a;i >= b;-- i)
 5 #define mem(a,b) memset((a),(b),sizeof((a)))
 6 #define FIN freopen("in.txt","r",stdin)
 7 #define IO ios_base::sync_with_stdio(0),cin.tie(0)
 8 #define pb push_back
 9 typedef long long LL;
10 typedef pair<int, int> PIR;
11 const int N = 1e6+5;
12 
13 string s;
14 int a[30];
15 
16 int main()
17 {
18     cin >> s;
19     rep(i, 0, s.size()-1)   a[s[i]-'a']++;
20     sort(a, a+26);
21     int ans = 0;
22     rep(i, 0, 23)   ans += a[i];
23     cout << ans << endl;
24     return 0;
25 }
View Code

 

F:
题意忘了, ans = max(ans, a[i]+a[n-i]); sort排序一下,遍历全部i便可;安全

 1 #include <bits/stdc++.h>
 2 using namespace std;
 3 #define rep(i,a,b) for(int i = a;i <= b;++ i)
 4 #define per(i,a,b) for(int i = a;i >= b;-- i)
 5 #define mem(a,b) memset((a),(b),sizeof((a)))
 6 #define FIN freopen("in.txt","r",stdin)
 7 #define IO ios_base::sync_with_stdio(0),cin.tie(0)
 8 #define pb push_back
 9 typedef long long LL;
10 typedef pair<int, int> PIR;
11 const int N = 1e6+5;
12 
13 int n, a[N];
14 
15 int main()
16 {
17     cin >> n;
18     rep(i, 1, n)    cin >> a[i];
19     sort(a+1, a+n+1);
20     int ans = 2e6+5;
21     rep(i, 1, n/2)  ans = min(ans, a[i]+a[n-i+1]);
22     cout << ans << endl;
23     return 0;
24 }
View Code

 

G:
签到题,按结构体排序ide

 1 #include <bits/stdc++.h>
 2 using namespace std;
 3 #define rep(i,a,b) for(int i = a;i <= b;++ i)
 4 #define per(i,a,b) for(int i = a;i >= b;-- i)
 5 #define mem(a,b) memset((a),(b),sizeof((a)))
 6 #define FIN freopen("in.txt","r",stdin)
 7 #define IO ios_base::sync_with_stdio(0),cin.tie(0)
 8 #define pb push_back
 9 typedef long long LL;
10 typedef pair<int, int> PIR;
11 const int N = 1e6+5;
12 
13 int n;
14 struct Node{
15     string s1, s2;
16     bool operator < (const Node &r) const {
17         if(s2 == r.s2)  return s1 < r.s1;
18         return s2 < r.s2;
19     }
20 }node[105];
21 
22 int main()
23 {
24     cin >> n;
25     rep(i, 1, n)    cin >> node[i].s1 >> node[i].s2;
26     sort(node+1, node+n+1);
27     rep(i, 1, n) cout << node[i].s1 << " " << node[i].s2 <<endl;
28     return 0;
29 }
View Code

 

H:
给定n段任务的三个属性 start(开始时间), val(价值), len(持续时间);
每一段时间都只能容许进行一种任务,如今求怎么安排能够获得一个最大的 tolval,输出这个最大的 tolval;spa

动态规划题,code

计dp[i]表示时间i以前最多能得到的fun值,初始化为0.  将全部活动按开始时间排序,时间从j=0开始,活动从i=1开始,blog

对于每个时间点,看是否有活动i在这个时间点开始,若是有,则更新dp[j+a[i].w]=max(dp[j+a[i].w],dp[j]+a[i].fun);

还有记得传递dp[j]给dp[j+1],dp[j+1]=max(dp[j+1],dp[j),由于前j时间能够得到的fun,j+1的时间也必定能够得到。(尊重版权 By - QAQ学长)

 1 #include<bits/stdc++.h>
 2 
 3 using namespace std;
 4 
 5 #define IO ios_base::sync_with_stdio(0),cin.tie(0)
 6 
 7 struct st{
 8    int s,l,v;
 9 }a[300005];
10 bool cmp(st b,st c){
11     return b.s<c.s;
12 }
13 int dp[2000005];
14 int main(){
15     IO;
16     int n;
17     int mx=0;
18     while(cin>>n){
19         memset(dp,0,sizeof(dp));
20         for(int i=1;i<=n;i++){
21             cin>>a[i].s>>a[i].v>>a[i].l;
22             mx=max(mx,a[i].s+a[i].l);
23         }
24         sort(a+1,a+1+n,cmp);
25         int i=1;
26         int result;
27         for(int j=0;j<=mx;j++){
28                 for(;i<=n;i++){
29                     if(a[i].s==j){
30                         dp[j+a[i].l]=max(dp[j+a[i].l],dp[j]+a[i].v);
31                     }
32                     else break;
33                 }
34             dp[j+1]=max(dp[j+1],dp[j]);
35         }
36         cout<<dp[mx]<<endl;
37     }
38     return 0;
39 }
View Code


I:
给定两个三角形的三条边,求能不能拼成矩形。拼成矩形须要知足两个条件;
一、每条边相等。 二、两个都是直角三角形;

 1 #include <bits/stdc++.h>
 2 using namespace std;
 3 #define rep(i,a,b) for(int i = a;i <= b;++ i)
 4 #define per(i,a,b) for(int i = a;i >= b;-- i)
 5 #define mem(a,b) memset((a),(b),sizeof((a)))
 6 #define FIN freopen("in.txt","r",stdin)
 7 #define IO ios_base::sync_with_stdio(0),cin.tie(0)
 8 #define pb push_back
 9 typedef long long LL;
10 typedef pair<int, int> PIR;
11 const int N = 1e6+5;
12 
13 int a[5], b[5];
14 
15 int main()
16 {
17     rep(i, 1, 3)    cin >> a[i];
18     rep(i, 1, 3)    cin >> b[i];
19     sort(a+1, a+4); sort(b+1, b+4);
20 
21     int ok = 1;
22     rep(i, 1, 3)    if(a[i] != b[i])    ok = 0;
23     if(ok){
24         if(a[1]*a[1]+a[2]*a[2] != a[3]*a[3])    ok = 0;
25     }
26     cout << (ok ? "YES" : "NO") << endl;
27     return 0;
28 }
View Code

 

J:
给你n个齿轮的圆心和半径,求第一个齿轮和最后一个齿轮的三种关系(保证出入数据不会存在两个齿轮相交的状况);
一、这个齿轮系统根本没法工做;
二、两个齿轮相离;
三、齿轮系统工做而且两个齿轮相连 (输出角速度的反比,逆向多输出一个负号);
解法:
1. 最多只有1000个齿轮,所以咱们能够先利用 n^2 的算法暴力判断每两个齿轮之间是否相切(即就是两圆相切);
2. 对于相切的两个齿轮,咱们能够建一条双向边,这样的话就转化成一个简单的图的问题;
3. 对于不能工做的状况就是样例三的那种状况,对于一个齿轮来讲,它能够有多个不一样的路径来带动它,可是存在带动的方向不一致。
即就是一个顺时针,一个逆时针。这种状况就是不能工做的。
4. 能够发现距离1号齿轮距离为奇数的齿轮都是都是和1号反向,偶数的都是同向,所以咱们能够利用bfs来解决该问题;
5. 利用bfs来求每一个点到一号齿轮的距离,若是有多个路径到达该齿轮,判断是否是3的不能工做的状况。最后判断是否是能够到达n号齿轮便可;

 1 #include <bits/stdc++.h>
 2 using namespace std;
 3 #define rep(i,a,b) for(int i = a;i <= b;++ i)
 4 #define per(i,a,b) for(int i = a;i >= b;-- i)
 5 #define mem(a,b) memset((a),(b),sizeof((a)))
 6 #define FIN freopen("in.txt","r",stdin)
 7 #define IO ios_base::sync_with_stdio(0),cin.tie(0)
 8 #define pb push_back
 9 typedef long long LL;
10 typedef pair<int, int> PIR;
11 const int N = 1e+5;
12 
13 int n, use, stu[N];
14 bool vis[N];
15 vector <int> G[N];
16 struct Node{
17     LL x, y;
18     LL r;
19 }node[N];
20 
21 bool judge(int i, int j){
22     LL xi = node[i].x-node[j].x, yi = node[i].y-node[j].y;
23     LL ri = node[i].r+node[j].r;
24     return (xi*xi+yi*yi) == ri*ri;
25 }
26 void Test(){
27     cout << "-----------TEST----------" << endl;
28     rep(i, 1, n){
29         cout << i << ": ";
30         rep(j, 0, (int)G[i].size()-1)   cout << G[i][j] << " ";
31         cout << endl;
32     }
33     cout << endl;
34 }
35 
36 void bfs(){
37     queue <PIR> Q;
38     mem(stu, -1);
39     mem(vis, false);
40     use = 1;
41     Q.push(PIR(1, 0));
42     stu[1] = 0;
43     vis[1] = true;
44     while(!Q.empty()){
45         PIR pir = Q.front(); Q.pop();
46         int u = pir.first, st = pir.second;
47         if(u == n){
48             if(st^0 == 1)   cout << "-";
49             LL gcd = __gcd(node[n].r, node[1].r);
50             cout << node[1].r/gcd << ":" << node[n].r/gcd << endl;
51             return ;
52         }
53         rep(i, 0, (int)G[u].size()-1){
54             int v = G[u][i];
55             if(stu[v] != -1 && stu[v]^st == 0){
56                 cout << "The input gear cannot move." << endl;
57                 return ;
58             }
59 
60             if(vis[v])  continue;
61             if(stu[v] == -1 || (stu[v] != -1 && stu[v]^st == 1)){
62                 stu[v] = st^1;
63                 vis[v] = true;
64                 Q.push(PIR(v, st^1));
65             }
66         }
67     }
68     cout << "The input gear is not connected to the output gear." << endl;
69     return ;
70 }
71 int main()
72 {IO;
73     //FIN;
74     cin >> n;
75     rep(i, 1, n)    cin >> node[i].x >> node[i].y >> node[i].r;
76     rep(i, 1, n)    rep(j, i+1, n)  if(judge(i, j)) { G[i].pb(j); G[j].pb(i); }
77     //Test();
78     bfs();
79     return 0;
80 }
View Code


K:
给你一个n*m的矩阵,每一个点有一个值,如今有k步操做,求k步以后矩阵种的不一样元素的个数;
每一步操做将矩形的每一个点变成周围数的和的平均值,若是超过边界,则从另外的边界补全;
n, m <= 100; k <= 9;直接暴力去变化就好了,注意每一个点的值须要用分数的形式表示;  (尊重版权 By - Yimismi)

 1 #include <bits/stdc++.h>
 2 using namespace std;
 3 #define rep(i,a,b) for(int i = a;i <= b;++ i)
 4 #define per(i,a,b) for(int i = a;i >= b;-- i)
 5 #define mem(a,b) memset((a),(b),sizeof((a)))
 6 #define FIN freopen("in.txt","r",stdin)
 7 #define IO ios_base::sync_with_stdio(0),cin.tie(0)
 8 #define pb push_back
 9 typedef long long ll;
10 struct Node
11 {
12     ll up, down;
13     Node() {};
14     Node(ll a, ll b) {up = a, down = b;}
15 } node[2][105][105];
16 bool operator < (const Node& t1, const Node& t2)
17 {
18     return t1.up*t2.down < t1.down*t2.up;
19 }
20 Node operator + (const Node& t1, const Node& t2)
21 {
22     Node ans;
23 
24     ans.down = t1.down*t2.down;
25     ans.up = t1.up*t2.down + t1.down*t2.up;
26     ll g = __gcd(ans.down, ans.up);
27     ans.down /= g;
28     ans.up /= g;
29     return ans;
30 }
31 int w, h, d;
32 void du(int x)
33 {
34     for(int i = 0; i < h; i++)
35     {
36         for(int j = 0; j < w; j++) cout << node[x][i][j].up << "/" << node[x][i][j].down << " " ; cout << endl;
37     }
38 }
39 Node solve(int u, int x, int y)
40 {
41     Node ans = Node(0, 1);
42     for(int i = (x - 1 + h)%h, time = 0; time < 3; time++, i = (i + 1)%h)
43     {
44         for(int j = (y - 1 + w)%w, time1 = 0; time1 < 3; time1++, j = (j + 1)%w)
45             ans = ans + node[u][i][j];
46     }
47 
48     ans.down *= 9;
49     ll g = __gcd(ans.up, ans.down);
50     ans.up /= g;
51     ans.down /= g;
52     //;cout << "-- "  << x << " " << y << " "<< ans.up << " " << ans.down << endl;
53     return ans;
54 }
55 void foo(int u)
56 {
57     int v = u^1;
58     for(int i = 0; i < h; i++)
59     {
60         for(int j = 0; j < w; j++)
61         {
62             node[v][i][j] = solve(u, i, j);
63         }
64     }
65 
66 }
67 set<Node> st;
68 int main()
69 {IO;
70     while(cin >> w >> h >> d)
71     {
72         for(int i = 0; i < h; i++)
73             for(int j = 0; j < w; j++)
74         {
75             int d;
76             cin >> d;
77             node[0][i][j].down = 1;
78             if(d == 0) node[0][i][j].up = 0;
79             else node[0][i][j].up = 1;
80         }
81         for(int i = 0; i < d; i++) foo(i&1);
82         st.clear();
83         for(int i = 0; i < h; i++)
84             for(int j = 0; j < w; j++)
85             {
86                 st.insert(node[d&1][i][j]);
87                // cout << node[d&1][i][j].up << " " << node[d&1][i][j].down << endl;
88             }
89         cout << st.size() << endl;
90 
91     }
92     return 0;
93 }
View Code