您的位置:首页 > 其它

CF#277.5div2

2014-11-18 20:58 525 查看
题目链接:codeforces.com/contest/489

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 277.5 div2