Winter Training #1
来源:互联网 发布:f100禁止mac访问 编辑:程序博客网 时间:2024/05/25 20:01
A
http://codeforces.com/problemset/problem/229/A
题意:给100个长1e4的01串,问最少的移动次数,造出一列全是1的
做法:我是把所有1找出来,如果有一行没有1显然gg。然后因为循环,所以在前面和后面各补一个。然后枚举1列的位置,对每行二分取到最小值求和即可。
代码:
#include <bits/stdc++.h>using namespace std;char str[105][10500];int cnt[105];int rec[105][10500];int main(){ int n, m; scanf("%d%d", &n, &m); for(int i=1;i<=n;i++)scanf("%s", str[i]+1); bool ok=true; for(int i=1;i<=n;i++){ bool flag=false; for(int j=1;j<=m;j++)if(str[i][j]=='1')flag=true; if(!flag){ ok=false; break; } } if(!ok){ printf("-1\n"); return 0; } memset(cnt, 0, sizeof(cnt)); for(int i=1;i<=n;i++){ for(int j=1;j<=m;j++)if(str[i][j]=='1')rec[i][++cnt[i]]=j; rec[i][0]=rec[i][cnt[i]]-m; rec[i][cnt[i]+1]=rec[i][1]+m; } int M=105*10500;/* for(int i=1;i<=n;i++){ for(int j=0;j<=cnt[i]+1;j++)printf("%d ", rec[i][j]); printf("\n"); }*/ for(int i=1;i<=m;i++){ int tmp=0; for(int j=1;j<=n;j++){ tmp+=min(i-*(upper_bound(rec[j], rec[j]+cnt[j]+2, i)-1), *(lower_bound(rec[j], rec[j]+cnt[j]+1, i))-i); } M=min(M, tmp); } printf("%d\n", M);}
B
http://codeforces.com/problemset/problem/229/B
题意:简单的最短路,附加条件是每个点有些时间不能走。
做法:在dij里改一下就行了。我一开始改了T了,后来发现因为会一直重复访问不能走的一段,加了一个d1数组防止重复访问就过了。
代码:
#include <bits/stdc++.h>using namespace std;struct edge{ int to, cost;};typedef pair<int, int> P;int n;vector<edge>g[105000];int d[105000];int d1[105000];vector<int>rec[105000];void dij(int s){ priority_queue<P, vector<P>, greater<P> >que; for(int i=1;i<=n;i++)d[i]=d1[i]=1e9+1e8; int st=0; for(vector<int>::iterator it=rec[s].begin();it!=rec[s].end();it++){ if(*it<st)continue; else if(*it==st)st++; else break; } d[s]=d1[s]=st; que.push(P(st, s)); while(!que.empty()){ P p=que.top();que.pop(); int v=p.second; if(d[v]<p.first)continue; for(vector<edge>::iterator it=g[v].begin();it!=g[v].end();it++){ edge e=*it; if(d1[e.to]>d[v]+e.cost){ d1[e.to]=d[e.to]=d[v]+e.cost; if(e.to==n)break; for(vector<int>::iterator it1=rec[e.to].begin();it1!=rec[e.to].end();it1++){ if(*it1<d[e.to])continue; else if(*it1==d[e.to])d[e.to]++; else break; } que.push(P(d[e.to], e.to)); } } }}int main(){ int m; scanf("%d%d", &n, &m); for(int i=1;i<=m;i++){ int a, b, c; scanf("%d%d%d", &a, &b, &c); edge t1, t2; t1.to=b, t1.cost=c; g[a].push_back(t1); t2.to=a, t2.cost=c; g[b].push_back(t2); } for(int i=1;i<=n;i++){ int num; scanf("%d", &num); for(int j=1;j<=num;j++) { int tmp; scanf("%d", &tmp); rec[i].push_back(tmp); } } dij(1); if(d[n]==1e9+1e8)printf("-1\n"); else printf("%d\n", d[n]);}
C
http://codeforces.com/contest/229/problem/C
题意:将一个1e6个点的完全图取1e6条边的子图,求这个子图和它的反图里一共有多少个三角形。
做法:考虑完全图的三角形数,是C(n,3);对于集合A、B,C(n,3)=由同1个集合的边构成的三角形+由A、B共同构成的三角形。所以我们只需要用C(n,3)减去三边分属于A、B集合的三角形即可。在一个n完全图中,一次拿掉一条边,与这条边有关的三角形有n-2个,减去n-2。但如果这条边的两端点已经有边,则减去n-2就多减了,作为补偿,要加上这两个点已有的边数,因为这些边和当前边确定的三角形已经在之前被减过了、
代码:
#include <bits/stdc++.h>using namespace std;typedef long long ll;ll rec[1050000];int main(){ memset(rec, 0, sizeof(rec)); ll n, m; scanf("%I64d%I64d", &n, &m); if(n<=2){ printf("0\n"); return 0; } ll ans=n*(n-1)*(n-2)/6; memset(rec, 0, sizeof(rec)); for(int i=1;i<=m;i++){ int x, y; scanf("%d%d", &x, &y); ans-=(n-2-rec[x]-rec[y]); rec[x]++; rec[y]++; } printf("%I64d\n", ans);}
因为po主太菜了,D和E不会,待赛后填坑吧。
E
http://codeforces.com/contest/229/problem/E
题意:略
做法:看了xhr大爷的题解后发现,我特么题少看了个条件就是同名的价格两两不同,之后的事情就是正常的概率dp了。注意dp存的是前i种物品取了j个边界值的所有情况的成功率之和,所以最后还要除掉所有情况的种类数。
代码:
#include <bits/stdc++.h>using namespace std;int n, m;int pre[1050];int rec[1050][1050];int tot;int cnt[1050];int upp[1050];bool exs[1050];int tag;double c[1050][1050];double dp[1050][1050];int main(){ scanf("%d%d", &n, &m); tot=0; for(int i=1;i<=m;i++){ scanf("%d", &cnt[i]); for(int j=1;j<=cnt[i];j++){ scanf("%d", &rec[i][j]); pre[++tot]=rec[i][j]; } } sort(pre+1, pre+1+tot); tag=pre[tot-n+1]; memset(exs, false, sizeof(exs)); memset(upp, 0, sizeof(upp)); for(int i=1;i<=m;i++){ for(int j=1;j<=cnt[i];j++){ if(rec[i][j]==tag)exs[i]=true; else if(rec[i][j]>tag)upp[i]++; } } for(int i=1;i<=1005;i++) for(int j=0;j<=i;j++){ if(j==0||j==i)c[i][j]=1; else c[i][j]=c[i-1][j-1]+c[i-1][j]; } int eql=0; int supp=0; for(int i=1;i<=m;i++)if(exs[i])eql++; for(int i=1;i<=m;i++)supp+=upp[i]; for(int i=0;i<=1005;i++)for(int j=0;j<=1005;j++)dp[i][j]=0; dp[0][0]=1; for(int i=1;i<=m;i++) for(int j=0;j<=n-supp;j++) { if(exs[i]&&j){ dp[i][j]=dp[i-1][j]/c[cnt[i]][upp[i]]+dp[i-1][j-1]/c[cnt[i]][upp[i]+1]; } else { dp[i][j]=dp[i-1][j]/c[cnt[i]][upp[i]]; } } printf("%.11f\n", dp[m][n-supp]/c[eql][n-supp]);}
- Winter Training #1
- SZU 2015 Winter Training Day#1
- KTU Programming Camp (Winter Training Day 1)
- 2016 Winter Training Day #1_C题_hdoj 1009(贪心)
- 2015 UESTC Winter Training #9
- 2016 Winter Training Day #1_A题_codefcrces 230A(贪心)
- 2016 Winter Training Day #1_B题_codefcrces 588A(贪心)
- 2016 Winter Training Day #1_D题_codefcrces 432A(贪心)
- 2016 Winter Training Day #1_E题_codefcrces 514A(贪心)
- 2016 Winter Training Day #1_F题_codefcrces 507A(贪心)
- 2016 Winter Training Day #1_G题_codefcrces 349A(贪心)
- Tri_integral Winter Training 0 比赛总结
- SZU 2015 Winter Training Day#2
- SZU 2015 Winter Training Day#3
- SZU 2015 Winter Training Day#4
- SZU 2015 Winter Training Day#5
- 2015 UESTC Winter Training 中的简单搜索
- SZU 2015 Winter Training Day#6
- Java语言概述
- use MFC in static LIB与use MFC in shared dll在下面这段程序的区别
- iOS各种设备信息获取总结
- Gradle for Android(三)多渠道打包、配置签名信息
- dom4j读取xml
- Winter Training #1
- C语言(24)------常用字符串处理函数大全
- day8:《Thinking in Java》笔记第九章---接口
- POJ 3295-Tautology(模拟-逻辑表达式)
- poj 1664 m个苹果放入n个盘子,递归写法和DP写法
- STL笔记介绍
- Live555 流媒体服务器启动
- Event处理(四)
- Android内存优化(使用SparseArray和ArrayMap代替HashMap)