码迷,mamicode.com
首页 > 其他好文 > 详细

Codeforces Round #485 (Div. 2)

时间:2018-06-09 18:55:27      阅读:175      评论:0      收藏:0      [点我收藏+]

标签:dfs   detail   二进制   lis   print   sort   eof   初始   排列   

C.http://codeforces.com/contest/987/problem/C

题意:从左到右有n个显示器,每个显示器都有一个高度h[i]和一个费用val[i],现在从中选出三个显示器,满足i<j<k&&h[i]<h[j]<h[k],求需要的最少费用

分析:设置数组dp[maxn],保存长度为2的LIS的最小花费,dp[i]=min(val[k]+val[i]) (k<i&&h[k]<h[i]) ans=min(dp[k]+val[i]) (k<i&&dp[k]!=初始值)

技术分享图片
 1 #include<cstdio>
 2 #include<cstring>
 3 #include<algorithm>
 4 using namespace std;
 5 typedef long long ll;
 6 const int maxn=3010;
 7 const int inf=1e9;
 8 int h[maxn],val[maxn];
 9 struct node{
10     int val1,val2;
11 }dp[maxn];
12 
13 int main()
14 {
15     int n,i,j,k,x,y,z,ans;
16     while ( scanf("%d",&n)!=EOF )
17     {
18         for ( i=1;i<=n;i++ ) scanf("%d",&h[i]);
19         for ( i=1;i<=n;i++ ) scanf("%d",&val[i]);
20         ans=inf;
21         for ( i=1;i<=n;i++ ) 
22         {
23             dp[i].val1=val[i];
24             dp[i].val2=inf;
25         }
26         for ( i=1;i<=n;i++ )
27         {
28             for ( j=1;j<i;j++ )
29             {
30                 if ( h[j]<h[i] ) 
31                 {
32                     dp[i].val2=min(dp[i].val2,dp[j].val1+val[i]);
33                     ans=min(ans,dp[j].val2+val[i]);
34                 }
35             }
36         }
37         if ( ans==inf ) printf("-1\n");
38         else printf("%d\n",ans);
39     }
40     return 0;
41 }
C

 

D.http://codeforces.com/contest/987/problem/D

题意:有n个仓市集,每个市集有一种特产,一共有k种特产,从一个市集可以移动到其他任意一个市集,路程是经过的边数。对于每个市集来说想要收集到k种不同的特产需要走的路程是多少

分析:因为k<=100,所以我们bfs考虑从特产数出发,设置d[i][k]表示第i个市集想要收集到第k个特产所需要的最少路程。对于每个特产单独bfs,最后对于每个市集收集不同特产的距离进行排序,取前s个

技术分享图片
 1 #include<cstdio>
 2 #include<cstring>
 3 #include<algorithm>
 4 #include<vector>
 5 #include<queue>
 6 using namespace std;
 7 const int maxn=1e5+10;
 8 const int maxm=110;
 9 const int inf=1e9;
10 int d[maxn][maxm];
11 vector<int>G[maxn];
12 vector<int>E[maxn];
13 int n,ans[maxn];
14 
15 void bfs(int x)
16 {
17     queue<int>que;
18     for ( int i=0;i<E[x].size();i++ )
19     {
20         int u=E[x][i];
21         d[u][x]=0;
22         que.push(u);
23     }
24     while ( !que.empty() )
25     {
26         int u=que.front();
27         que.pop();
28         for ( int i=0;i<G[u].size();i++ )
29         {
30             int v=G[u][i];
31             if ( d[v][x]==inf )
32             {
33                 d[v][x]=d[u][x]+1;
34                 que.push(v);
35             }
36         }
37     }
38 }
39 
40 int main()
41 {
42     int m,k,s,i,j,x,y,z,u,v,sum;
43     while ( scanf("%d%d%d%d",&n,&m,&k,&s)!=EOF )
44     {
45         for ( i=1;i<=n;i++ ) G[i].clear();
46         for ( i=1;i<=k;i++ ) E[i].clear();
47         for ( i=1;i<=n;i++ )
48         {
49             for ( j=1;j<=k;j++ ) d[i][j]=inf;
50         }
51         for ( i=1;i<=n;i++ ) 
52         {
53             scanf("%d",&x);
54             E[x].push_back(i);
55         }
56         for ( i=1;i<=m;i++ )
57         {
58             scanf("%d%d",&u,&v);
59             G[u].push_back(v);
60             G[v].push_back(u);
61         }
62         for ( i=1;i<=k;i++ ) bfs(i);
63         for ( i=1;i<=n;i++ )
64         {
65             sort(d[i]+1,d[i]+1+k);
66             sum=0;
67             for ( j=1;j<=s;j++ ) sum+=d[i][j];
68             ans[i]=sum;
69         }
70         for ( i=1;i<=n;i++ )
71         {
72             printf("%d",ans[i]);
73             if ( i!=n ) printf(" ");
74             else printf("\n");
75         }
76     }
77     return 0;
78 }
D

 

E.http://codeforces.com/contest/987/problem/E

以下分析来自:https://blog.csdn.net/Stupid_Turtle/article/details/80514590

题意:Petr和Alex两个人对一个初始为1,2,3,...,n的长度为n的排列有不同的操作次数(一次操作表现为将其中两个数交换位置,比如1,2,3,4变为1,2,4,3称为一次操作),Petr会对其进行3n次操作,而Alex会对其进行7n+1次操作。现在给你初始排列的长度n和结果排列,问你是他们中的谁进行的操作,如果是Petr输出"Petr",否则输出"Um_nik"。

分析:利用到排列的性质:对于一个排列,他所包含的逆序数的对数称为它的逆序数,逆序数为奇数的排列称为奇排列,逆序数为偶数的排列称为偶排列,调换一个奇排列中两个数的位置可以把它变成偶排列,同样,调换一个偶排列中的两个数的位置可以把他变成奇排列。

那么显然,初始排列1,2,...,n的逆序数为0,这样只要求出结果排列的逆序数就可以知道到底进行了奇数次还是偶数次操作。而当n为奇数的时候,3n为奇,7n+1为偶;当n为偶数的时候,3n为偶,7n+1为奇。那么根据n的奇偶性和结果逆序数的奇偶性,就可以知道是谁进行的操作。

技术分享图片
 1 #include<cstdio>
 2 #include<cstring>
 3 #include<algorithm>
 4 using namespace std;
 5 typedef long long ll;
 6 const int maxn=1e6+10;
 7 ll bit[maxn];
 8 ll n,a[maxn];
 9 
10 ll lowbit(ll x)
11 {
12     return x&(-x);
13 }
14 
15 void add(ll k)
16 {
17     while ( k<=n )
18     {
19         bit[k]++;
20         k+=lowbit(k);
21     }
22 }
23 
24 ll sum(ll k)
25 {
26     ll s=0;
27     while ( k )
28     {
29         s+=bit[k];
30         k-=lowbit(k);
31     }
32     return s;
33 }
34 
35 int main()
36 {
37     ll m,i,j,k,x;
38     ll ans;
39     while ( scanf("%lld",&n)!=EOF )
40     {
41         memset(bit,0,sizeof(bit));
42         ans=0;
43         for ( i=1;i<=n;i++ ) 
44         {
45             scanf("%lld",&x);
46             add(x);
47             ans+=(i-sum(x));
48         }
49         if ( n%2 == ans%2 ) printf("Petr\n");
50         else printf("Um_nik\n");
51     } 
52     return 0;
53 }
E

 

F.http://codeforces.com/contest/987/problem/F

题意:给出m个数,对于某两个数x,y,如果有x&y==0,那么在x和y之间连一条边,先求有几个连通块

分析:对于某个数x,只有当x和y的二进制含1的位置不同才能连一条边。考虑搜索,所有数的最大值为A=(1<<n)-1。对于x,考虑x^A(op==1,op=0表示第一次dfs)及其子集(去掉其中的部分1,一次dfs可以去掉二进制中的一个1)

技术分享图片
 1 #include<cstdio>
 2 #include<cstring>
 3 #include<algorithm>
 4 using namespace std;
 5 const int maxn=(1<<22)+5;
 6 int a[maxn],n,m,A;
 7 bool vis[maxn],have[maxn];
 8 
 9 void dfs(int u,int op)
10 {
11     vis[u]=true;
12     if ( !vis[u^A] && have[u] ) dfs(u^A,1);
13     if ( op==0 ) return;
14     for ( int i=0;i<n;i++ )
15     {
16         if ( u&(1<<i) )
17         {
18             int v=u^(1<<i);
19             if ( !vis[v] ) dfs(v,1);
20         }
21     }
22 }
23 
24 int main()
25 {
26     int i,j,k,x,y,z,u,v,ans;
27     while ( scanf("%d%d",&n,&m)!=EOF )
28     {
29         memset(vis,false,sizeof(vis));
30         memset(have,false,sizeof(have));
31         for ( i=1;i<=m;i++ ) 
32         {
33             scanf("%d",&a[i]);
34             have[a[i]]=true;
35         }
36         A=(1<<n)-1;
37         ans=0;
38         for ( i=1;i<=m;i++ )
39         {
40             if ( !vis[a[i]] ) 
41             {
42                 dfs(a[i],0);
43                 ans++;
44             }
45         }
46         printf("%d\n",ans);
47     }
48     return 0;
49 }
F

 

Codeforces Round #485 (Div. 2)

标签:dfs   detail   二进制   lis   print   sort   eof   初始   排列   

原文地址:https://www.cnblogs.com/HDUjackyan/p/9160362.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!