题目链接: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\n", ans); 33 } 34 return 0; 35 }
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, " \n"[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, " \n"[i==n-1]); 53 num--; 54 } else printf("%d%c", 1, " \n"[i==n-1]); 55 } 56 } 57 } 58 } 59 return 0; 60 }
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 }
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\n", ansA/sum, ansB/sum, ansC/sum); 49 } 50 return 0; 51 }
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<<"\tpos: "<<p<<endl; 83 ans+=fw.query(tn)-fw.query(p); 84 // cout<<fw.query(tn)<<"\t"<<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)<<"\t"<<fw.query(q)<<endl; 91 fw.update(q+1, num); 92 } 93 } 94 printf("%I64d\n", ans); 95 } 96 return 0; 97 }