CF#277.5div2
2014-11-18 20:58
525 查看
题目链接:codeforces.com/contest/489
A题:
思路:裸地选择排序,不过我的做法是先排序然后一直迭代输出
B题:
思路:第一反应是二分图的最大匹配,然后就没多想,看官方题解原来可以排序贪心做,,-_-|||,,
C题:
思路:简单构造题,贪心去做,最大可能的数是尽可能让高位的数字越大,最小可能的数是先让第一位为1,然后让低位的数字尽可能的大,,
D题:
思路:就是枚举每一个点,以该点为菱形的起点,然后标记访问到的孙子结点被访问的次数cnt,两两组合就是cnt*(cnt-1)/2个菱形,,不过我代码实现是逐个累加的,,
E题:
思路:看题解是分数规划做的,
r=seg( | ri - l | )/seg( bi ) 转化成 z(r) = seg( | ri - l | ) - r*seg(bi) 的一个函数,然后可以证明 z(r) 是个单调递减函数 ,所以可以用二分r,然后DP(n^2)算出dp
的最小花费,
当z(r) >0 ,说明还可以增大r来优化
当z(r)==0,则最优
当z(r)<0,则可以减小r来优化
DP方程:dp[i] = max{ dp[j] + sqrt(fabs(xi[i]-xi[j]-l))-r*bi[i] }
F题:
思路:记忆化搜索实现,先统计出每列还能放2个'1'的列数x,和每列还能放1个'1'的列数y,
因为每行必须放两个1,所以转移方程如下:
DP(x,y) = DP(x-2,y+2) *x*(x-1)/2 该行从x中选两个放1,然后每列'1'为1个的数目y+2,每列'1'为2个的数目x-2
+DP(x,y-2)*y*(y-1)/2 该行从y中选两个放1,然后每列'1'为1个的数目y-2
+DP(x-1,y)*x*y 该行分别从x和y中各选一个放1,然后每列'1'为1个的数目y,每列'1'为2个的数目x-1
注意边界:x<0 or y<0 说明该构造不符合要求,返回0; x==0 and y==0 说明构造刚好符合,返回1
A题:
思路:裸地选择排序,不过我的做法是先排序然后一直迭代输出
#include<bits/stdc++.h> using namespace std; struct Node{ int v; int id; bool operator < (const Node& p)const{ return v<p.v; } } node[3007]; bool vis[3007]; vector<int> ans; int main(){ int n; cin>>n; for(int i=0;i<n;++i){ scanf("%d",&node[i].v); node[i].id=i; } sort(node,node+n); int cnt=0,idx=0,pos=0; memset(vis,false,sizeof(vis)); bool flag=false; while(cnt<n){ if(!flag){ while(vis[pos]) pos++; idx=pos; } flag=false; if(!vis[node[idx].id]){ ans.push_back(idx); ans.push_back(node[idx].id); flag=true; } vis[idx]=true; cnt++; if(flag) idx=node[idx].id; } printf("%d\n",ans.size()/2); for(int i=0;i<ans.size();i+=2){ printf("%d %d\n",ans[i],ans[i+1]); } return 0; }
B题:
思路:第一反应是二分图的最大匹配,然后就没多想,看官方题解原来可以排序贪心做,,-_-|||,,
#include <bits/stdc++.h> using namespace std; bool vis[105],mp[105][105]; int mat[105],a[105],b[105]; int n,m; bool find(int x){ for(int y=1;y<=m;++y){ if(!mp[x][y]) continue; if(vis[y]) continue; vis[y]=true; if(mat[y]==-1||find(mat[y])){ mat[y]=x; return true; } } return false; } int main(){ cin>>n; for(int i=1;i<=n;++i) cin>>a[i]; cin>>m; for(int i=1;i<=m;++i) cin>>b[i]; memset(mp,false,sizeof(mp)); for(int i=1;i<=n;++i) for(int j=1;j<=m;++j) if(abs(a[i]-b[j])<=1) mp[i][j]=true; int ans=0; memset(mat,-1,sizeof(mat)); for(int i=1;i<=n;++i){ memset(vis,false,sizeof(vis)); if(find(i)) ans++; } cout<<ans<<endl; return 0; }
C题:
思路:简单构造题,贪心去做,最大可能的数是尽可能让高位的数字越大,最小可能的数是先让第一位为1,然后让低位的数字尽可能的大,,
#include <bits/stdc++.h> using namespace std; int m,s; int sa[105],sb[105]; void work(){ memset(sa,0,sizeof(sa)); memset(sb,0,sizeof(sb)); int tmp=s-1; sa[1]=1; for(int i=m;i>=1;--i){ if(tmp>=9){ sa[i]+=9; tmp-=9; } else{ sa[i]+=tmp; break; } } tmp=s; for(int i=1;i<=m;++i){ if(tmp>=9){ sb[i]+=9; tmp-=9; } else{ sb[i]+=tmp; break; } } for(int i=1;i<=m;++i) printf("%d",sa[i]); putchar(' '); for(int i=1;i<=m;++i) printf("%d",sb[i]); puts(""); } int main(){ cin>>m>>s; if(s>m*9||m>1&&s<1) puts("-1 -1"); else work(); return 0; }
D题:
思路:就是枚举每一个点,以该点为菱形的起点,然后标记访问到的孙子结点被访问的次数cnt,两两组合就是cnt*(cnt-1)/2个菱形,,不过我代码实现是逐个累加的,,
#include <bits/stdc++.h> using namespace std; int n,m,ans; vector<int> p[3005]; int vis[3005],cnt[3005]; void dfs(int u,int root,int dep){ if(dep==2){ if(u==root) return ; if(vis[u]!=root){ vis[u]=root; cnt[u]=1; } else{ ans+=cnt[u]; cnt[u]++; } return ; } for(int i=0;i<p[u].size();++i){ dfs(p[u][i],root,dep+1); } } int main(){ cin>>n>>m; for(int i=1;i<=n;++i) p[i].clear(); while(m--){ int u,v; scanf("%d%d",&u,&v); p[u].push_back(v); } ans=0; for(int i=1;i<=n;++i){ if(p[i].size()>=2) dfs(i,i,0); } cout<<ans<<endl; return 0; }
E题:
思路:看题解是分数规划做的,
r=seg( | ri - l | )/seg( bi ) 转化成 z(r) = seg( | ri - l | ) - r*seg(bi) 的一个函数,然后可以证明 z(r) 是个单调递减函数 ,所以可以用二分r,然后DP(n^2)算出dp
的最小花费,
当z(r) >0 ,说明还可以增大r来优化
当z(r)==0,则最优
当z(r)<0,则可以减小r来优化
DP方程:dp[i] = max{ dp[j] + sqrt(fabs(xi[i]-xi[j]-l))-r*bi[i] }
#include <bits/stdc++.h> using namespace std; const int N =1005; const double EPS = 1e-9; double dp ; int pre ,sta ; int xi ,bi ; int n,l; // 分数规划: z(r) = seg(sqrt(ri-l)) - seg(r*bi) bool DP(double mid){ dp[0]=xi[0]=bi[0]=0; for(int i=1;i<=n;++i){ dp[i]=1e10; for(int j=0;j<i;++j){ double tmp = dp[j]+sqrt(fabs(xi[i]-xi[j]-l)) - mid*bi[i]; if(tmp<dp[i]){ dp[i]=tmp; pre[i]=j; } } } if(dp >-EPS) return true; else return false; } int main(){ ios_base::sync_with_stdio(0); cin.tie(0); cin>>n>>l; for(int i=1;i<=n;++i) cin>>xi[i]>>bi[i]; double l=0,r=1e9; while(l+EPS<r){ double mid=(l+r)/2; if(DP(mid)) l=mid; else r=mid; } int idx=n,top=0; while(idx){ sta[top++]=idx; idx=pre[idx]; } for(int i=top-1;i>=0;--i) printf("%d%c",sta[i],i==0?'\n':' '); return 0; }
F题:
思路:记忆化搜索实现,先统计出每列还能放2个'1'的列数x,和每列还能放1个'1'的列数y,
因为每行必须放两个1,所以转移方程如下:
DP(x,y) = DP(x-2,y+2) *x*(x-1)/2 该行从x中选两个放1,然后每列'1'为1个的数目y+2,每列'1'为2个的数目x-2
+DP(x,y-2)*y*(y-1)/2 该行从y中选两个放1,然后每列'1'为1个的数目y-2
+DP(x-1,y)*x*y 该行分别从x和y中各选一个放1,然后每列'1'为1个的数目y,每列'1'为2个的数目x-1
注意边界:x<0 or y<0 说明该构造不符合要求,返回0; x==0 and y==0 说明构造刚好符合,返回1
#include <cstdio> #include <cstring> #include <string> #include <iostream> #include <algorithm> using namespace std; typedef long long LL; const int N = 505; LL col ,dp ; bool vis ; LL n,m,mod; LL DP(int x,int y){ if(x<0||y<0) return 0; if(x==0&&y==0) return 1; if(vis[x][y]) return dp[x][y]; LL a=(x*(x-1)/2*DP(x-2,y+2))%mod; LL b=(y*(y-1)/2*DP(x,y-2))%mod; LL c=(x*y*DP(x-1,y))%mod; dp[x][y]=(a+b+c)%mod; vis[x][y]=true; return dp[x][y]; } int main(){ ios_base::sync_with_stdio(0); cin.tie(0); cin>>n>>m>>mod; for(int i=0;i<m;++i){ string s; cin>>s; for(int j=0;j<n;++j) if(s[j]=='1') col[j]++; } int one=0,two=0; for(int 4000 i=0;i<n;++i){ if(col[i]==0) two++; if(col[i]==1) one++; } cout<<DP(two,one)<<endl; //system("pause"); return 0; }
相关文章推荐
- Cf 363div2 A B C
- 【打CF,学算法——二星级】Codeforces 705B Spider Man (简单博弈)
- >>关于.NET CF 的一些知识——启动同一个程序的多个拷贝
- cf gym101061J Cola(优先队列)
- .net cf的label问题
- CF 219D Choosing Capital for Treeland (树形dp)
- .Net CF下精确的计时器
- 【CF 534F】Game
- .Net CF 开发菜鸟笔记(PDA应用开发)
- [CF]-Continued Fractions
- PXA270处理器PCMCIA/CF接口设计及WinCE5.0驱动实现
- ccf201604-4 游戏
- [讨论]一个关屏程序分别用c#.net cf 和 evc++实现的不同
- CF 710C Magic Odd Square
- 用 Eclipse CFEclipse 插件快速编写 ColdFusion 应用程序
- CCF201604-4 90分
- [CF.Skills].Net CF中电话状态的捕获(Part 1)
- CF 540E, 树状数组
- Ensuring CF As an E-Commerce Platform @ JDJ
- cf 50A. Domino piling 贪心