Codeforces Round #301 (Div. 2) 题解

题目链接:http://codeforces.com/contest/540

A、题意:你现在要解开一个密码锁,给你当前密码锁的状态和目标状态,你要拨动最少次数到达目标状态

解:贪心

 1 /*
 2  * Problem:  
 3  * Author:  SHJWUDP
 4  * Created Time:  2015/6/4 星期四 15:06:51
 5  * File Name: 233.cpp
 6  * State: 
 7  * Memo: 
 8  */
 9 #include <iostream>
10 #include <cstdio>
11 #include <cstring>
12 #include <algorithm>
13 
14 using namespace std;
15 
16 const int MaxA=1e3+7;
17 
18 char strA[MaxA];
19 char strB[MaxA];
20 int main() {
21 #ifndef ONLINE_JUDGE
22     freopen("in", "r", stdin);
23     //freopen("out", "w", stdout);
24 #endif
25     int n;
26     while(~scanf("%d", &n)) {
27         scanf("%s%s", strA, strB);
28         int ans=0;
29         for(int i=0; i<n; i++) {
30             ans+=min(abs(strA[i]-strB[i]), min(strA[i], strB[i])+10-max(strA[i], strB[i]));
31         }
32         printf("%d
", ans);
33     }
34     return 0;
35 }
View Code

B、题意:现在有n门课要考试(n是奇数),每门的总分都是p且最少都要考1分,现在已经考了k门(k门成绩给出了),问你要总分小于x且,各门考分的中位数大于y该怎么考,如果有多解,输出任意一个即可

解:贪心,一种构造方法:比y大的数如果小于n/2个,那么中位数一定取y,然后比中位数大的数有空缺就拿y补充,比中位数小的数拿1补充

 1 /*
 2  * Problem:  
 3  * Author:  SHJWUDP
 4  * Created Time:  2015/6/4 星期四 15:06:51
 5  * File Name: 233.cpp
 6  * State: 
 7  * Memo: 
 8  */
 9 #include <iostream>
10 #include <cstdio>
11 #include <cstring>
12 #include <algorithm>
13 
14 using namespace std;
15 
16 typedef long long int64;
17 
18 const int MaxA=1e3+7;
19 
20 int64 n, k, p, x, y;
21 int64 arr[MaxA];
22 int main() {
23 #ifndef ONLINE_JUDGE
24     freopen("in", "r", stdin);
25     //freopen("out", "w", stdout);
26 #endif
27     while(~scanf("%I64d%I64d%I64d%I64d%I64d", &n, &k, &p, &x, &y)) {
28         int64 sum=0;
29         int cnt=0;
30         for(int i=0; i<k; i++) {
31             scanf("%I64d", &arr[i]);
32             sum+=arr[i];
33             if(arr[i]>=y) cnt++;
34         }
35         if(sum+n-k>x) {
36             puts("-1"); continue;
37         }
38 
39         int need=(n>>1)+1;
40         if(cnt>=need) {
41             for(int i=k; i<n; i++) {
42                 printf("%d%c", 1, " 
"[i==n-1]);
43             }
44         } else {
45             int tmp=need-cnt;
46             if(tmp>n-k || sum+tmp*y+(n-k-tmp)>x) {
47                 puts("-1");
48             } else {
49                 int num=tmp;
50                 for(int i=k; i<n; i++) {
51                     if(num) {
52                         printf("%I64d%c", y, " 
"[i==n-1]);
53                         num--;
54                     } else printf("%d%c", 1, " 
"[i==n-1]);
55                 }
56             }
57         }
58     }
59     return 0;
60 }
View Code

C、题意:冰洞游戏,你在一张n*m的地图上(你占一个格子的空间),地图上的每个格子有两种状态,'X':踩在上面会掉下去,'.':踩在上面会变成'X',给你初始位置和目标位置,问你是否能够在目标位置掉下去

解:搜索+贪心,看看能不能从到达目标位置,再根据目标位置的状态与度数判断是否可以掉下去,有初始位置和目标位置相邻或重合的时候需要特判一下

 1 /*
 2  * Problem:  
 3  * Author:  SHJWUDP
 4  * Created Time:  2015/6/4 星期四 15:06:51
 5  * File Name: 233.cpp
 6  * State: 
 7  * Memo: 
 8  */
 9 #include <iostream>
10 #include <cstdio>
11 #include <cstring>
12 #include <algorithm>
13 #include <queue>
14 
15 using namespace std;
16 
17 typedef long long int64;
18 
19 const int MaxA=500+7;
20 
21 int n, m;
22 char map[MaxA][MaxA];
23 int dir[][2]={{0, 1}, {1, 0}, {-1, 0}, {0, -1}};
24 int sx, sy, tx, ty;
25 bool bfs() {
26     queue<pair<int, int> > Q;
27     Q.push(make_pair(sx, sy));
28     while(!Q.empty()) {
29         pair<int, int> u=Q.front(); Q.pop();
30         for(int k=0; k<4; k++) {
31             int xx=u.first+dir[k][0];
32             int yy=u.second+dir[k][1];
33             if(xx<0 || xx>=n || yy<0 || yy>=m) continue;
34             if(xx==tx && yy==ty) return true;
35             if(map[xx][yy]=='X') continue;
36             map[xx][yy]='X';
37             Q.push(make_pair(xx, yy));
38         }
39     }
40     return false;
41 }
42 int main() {
43 #ifndef ONLINE_JUDGE
44     freopen("in", "r", stdin);
45     //freopen("out", "w", stdout);
46 #endif
47     while(~scanf("%d%d", &n, &m)) {
48         for(int i=0; i<n; i++) {
49             scanf("%s", map[i]);
50         }
51         scanf("%d%d%d%d", &sx, &sy, &tx, &ty);
52         sx--; sy--; tx--; ty--;
53         int dg=0;
54         for(int k=0; k<4; k++) {
55             int xx=tx+dir[k][0];
56             int yy=ty+dir[k][1];
57             if(xx<0 || xx>=n || yy<0 || yy>=m) continue;
58             if(map[xx][yy]!='X' || (xx==sx && yy==sy)) dg++;
59         }
60         if(sx==tx && sy==ty) {
61             puts(dg>=1?"YES":"NO");
62             continue;
63         }
64     //  cout<<"dg: "<<dg<<endl;
65     //  cout<<"flag; "<<bfs()<<endl;
66         if(((dg>=2 && map[tx][ty]=='.') || map[tx][ty]=='X')
67                 && bfs()) {
68             puts("YES");
69         } else puts("NO");
70     }
71     return 0;
72 }
View Code

D、题意:在一个岛上住着石头、剪刀、布三种生物,告诉你每种生物的数量r,s,p问你在无限长的时间后最后存活的生物是石头,剪刀还是布的概率分别是多少

解:三维dp,注意转移的话有概率会维持原状态,那么对于转移概率实际上是目标状态概率/生物消减概率

 1 /*
 2  * Problem:  
 3  * Author:  SHJWUDP
 4  * Created Time:  2015/6/4 星期四 15:06:51
 5  * File Name: 233.cpp
 6  * State: 
 7  * Memo: 
 8  */
 9 #include <iostream>
10 #include <cstdio>
11 #include <cstring>
12 #include <algorithm>
13 #include <queue>
14 
15 using namespace std;
16 
17 typedef long long int64;
18 
19 const double eps=1e-10;
20 
21 const int MaxA=100+7;
22 
23 int r, s, p;
24 double f[MaxA][MaxA][MaxA];
25 int main() {
26 #ifndef ONLINE_JUDGE
27     freopen("in", "r", stdin);
28     //freopen("out", "w", stdout);
29 #endif
30     while(~scanf("%d%d%d", &r, &s, &p)) {
31         memset(f, 0, sizeof(f));
32         f[r][s][p]=1;
33         for(int i=r; i>=0; i--) {
34             for(int j=s; j>=0; j--) {
35                 for(int k=p; k>=0; k--) {
36                     double p1=i*k, p2=i*j, p3=j*k;
37                     if(k && i) f[i-1][j][k]+=f[i][j][k]*p1/(p1+p2+p3);
38                     if(i && j) f[i][j-1][k]+=f[i][j][k]*p2/(p1+p2+p3);
39                     if(j && k) f[i][j][k-1]+=f[i][j][k]*p3/(p1+p2+p3);
40                 }
41             }
42         }
43         double ansA=0, ansB=0, ansC=0;
44         for(int i=1; i<=r; i++) ansA+=f[i][0][0];
45         for(int i=1; i<=s; i++) ansB+=f[0][i][0];
46         for(int i=1; i<=p; i++) ansC+=f[0][0][i];
47         double sum=ansA+ansB+ansC;
48         printf("%.12f %.12f %.12f
", ansA/sum, ansB/sum, ansC/sum);
49     }
50     return 0;
51 }
View Code

E、题意:给你一个无限长的序列{1,2,3,...},问你在执行交换操作n次后的逆序数

解:树状数组求逆序数,经典题变体,需要考虑参与交换的元素与交换元素之间的元素

 1 /*
 2  * Problem:  
 3  * Author:  SHJWUDP
 4  * Created Time:  2015/6/8 星期一 16:51:21
 5  * File Name: 233.cpp
 6  * State: 
 7  * Memo: 
 8  */
 9 #include <iostream>
10 #include <cstdio>
11 #include <cstring>
12 #include <algorithm>
13 
14 using namespace std;
15 
16 typedef long long int64;
17 
18 const int MaxA=1e5+7;
19 const int MaxB=MaxA<<1;
20 
21 struct Fenwick {
22     int n;
23     int c[MaxB];
24 
25     void init(int _n) {
26         this->n=_n;
27         memset(c, 0, sizeof(c[0])*(n+3));
28     }
29 
30     int lowbit(int x) {
31         return x&-x;
32     }
33 
34     void update(int x, int v) {
35         while(x<=n) {
36             c[x]+=v;
37             x+=lowbit(x);
38         }
39     }
40 
41     int query(int x) {
42         int res=0;
43         while(x>0) {
44             res+=c[x];
45             x-=lowbit(x);
46         }
47         return res;
48     }
49 } fw;
50 
51 int n;
52 pair<int, int> op[MaxA];
53 int table[MaxB], tn;
54 int arr[MaxB], an;
55 int find(int x) {
56     return lower_bound(table, table+tn, x)-table;
57 }
58 int main() {
59 #ifndef ONLINE_JUDGE
60     freopen("in", "r", stdin);
61     //freopen("out", "w", stdout);
62 #endif
63     while(~scanf("%d", &n)) {
64         tn=0;
65         for(int i=0; i<n; i++) {
66             scanf("%d%d", &op[i].first, &op[i].second);
67             table[tn++]=op[i].first;
68             table[tn++]=op[i].second;
69         }
70         sort(table, table+tn);
71         tn=unique(table, table+tn)-table;
72         memcpy(arr, table, tn*sizeof(table[0]));
73         an=tn;
74 
75         for(int i=0; i<n; i++) {
76             swap(arr[find(op[i].first)], arr[find(op[i].second)]);
77         }
78         fw.init(tn);
79         int64 ans=0;
80         for(int i=0; i<an; i++) {
81             int p=find(arr[i])+1;
82         //  cout<<"tn: "<<tn<<"	pos: "<<p<<endl;
83             ans+=fw.query(tn)-fw.query(p);
84         //  cout<<fw.query(tn)<<"	"<<fw.query(p)<<endl;
85             if(i!=an-1) {
86                 int q=find(table[i])+1;
87                 fw.update(p, 1);
88                 int num=table[i+1]-table[i]-1;
89                 ans+=(int64)num*(fw.query(tn)-fw.query(q));
90             //  cout<<fw.query(tn)<<"	"<<fw.query(q)<<endl;
91                 fw.update(q+1, num);
92             }
93         }
94         printf("%I64d
", ans);
95     }
96     return 0;
97 }
View Code
原文地址:https://www.cnblogs.com/shjwudp/p/4561889.html