首页 > 代码库 > Codeforces 417 Div.2

Codeforces 417 Div.2

A.给你1、2、3、4道路上的车和行人当前的红绿灯状况(绿灯:1、红灯:0)

问:各个道路上的汽车是否会撞到其他道路上的行人

技术分享

记录会出现汽车的道路编号,判断此时该道路上是否有行人即可

 1 #include <bits/stdc++.h>
 2 using namespace std;
 3 
 4 int a[5][5];
 5 int vis[5];
 6 int b[4]={1,2,3,4};
 7 int main()
 8 {
 9     for(int i=1; i<=4; i++)
10     {
11         for(int j=0; j<4; j++)
12             scanf("%d",&a[i][j]);
13         for(int j=0; j<3; j++)
14             if(a[i][j]==1)
15             {
16                 vis[i]=1;   //标记会出现车辆的道路
17                 vis[b[(2-j+i)%4]]=1; //同上
18             }
19     }
20     int flag=0;
21     for(int i=1; i<=4; i++)
22         if(a[i][3]==1 && vis[i]==1)  //若有行人,则YES
23             flag=1;
24     if(flag) cout<<"YES"<<endl;
25     else cout<<"NO"<<endl;
26     return 0;
27 }

B.给你n层楼,每层有m+2个,左右分别为0,代表楼梯,剩下m个房间1表示有人,0则没有人,走一个耗时1

开始位置位于左下角,问:需要的最少的时间是多少

Examples
input
2 2
0010
0100
output
5
input
3 4
001000
000010
000010
output
12
input
4 3
01110
01110
01110
01110
output
18
先记录每层的有人房间的最左的位置,最右位置。
用dp[i][0]表示走到i层的左楼梯的最少步数,dp[i][1]表示走到i层的右楼梯的最少步数,递推关系式,就能推出来了。
 1 #include <bits/stdc++.h>
 2 using namespace std;
 3 
 4 char s[20][105];
 5 int dp[20][2];
 6 int l[20],r[20];
 7 
 8 int main()
 9 {
10     int n,m;
11     scanf("%d%d",&n,&m);
12     for(int i=n; i>=1; i--)
13     {
14         scanf("%s",s[i]);
15         int flag=0;
16         for(int j=0; j<m+2; j++)
17             if(s[i][j]==1) r[i]=j,flag=1;
18         for(int j=m+1; j>=0; j--)
19             if(s[i][j]==1) l[i]=j,flag=1;
20         if(!flag) r[i]=l[i]=0;  //记录下最左最右房间位置,若该层没有,记为0
21     }
22     dp[1][0]=0,dp[1][1]=m+1;  //第一层dp结果是确定的
23     for(int i=2; i<=n; i++)
24     {
25         if(l[i-1])  //前一层有房间的话
26         {
27             dp[i][0]=min(dp[i-1][0]+r[i-1]*2+1,dp[i-1][1]+m+2);  //+1是要向上一层
28             dp[i][1]=min(dp[i-1][0]+m+2,dp[i-1][1]+(m+1-l[i-1])*2+1);
29         }
30         else 
31         {
32             dp[i][0]=min(dp[i-1][0]+1,dp[i-1][1]+m+2);  //该层没人,直接向上走
33             dp[i][1]=min(dp[i-1][0]+m+2,dp[i-1][1]+1);
34         }
35     }
36     int ans,flag=0;
37     for(int i=n; i>=1; i--)
38         if(l[i])  //最后再判断最后有人的一层的最小情况
39         {
40             ans=min(dp[i][0]+r[i],dp[i][1]+m+1-l[i]);
41             flag=1;
42             break;
43         }
44     printf("%d",flag ? ans : 0);  //可能出现全为0的情况
45     return 0;
46 }

C.给你n件物品的价格,和s的预算,问你最多能买几件物品,若最大物品数相同,则要使花费最少

sumPrice=cnt件物品的价格之和+cnt件物品的下标和×件数

Examples
input
3 11
2 3 5
output
2 11
input
4 100
1 2 5 6
output
4 54
input
1 7
7
output
0 0
我们这样考虑:把cnt件的下标和×cnt,分配到每件上,那么其实每件的价格+=cnt×自己的下标,那么对于某一个cnt来说,不妨把所有的物品价格都+=cnt×自己下标,再sort以下,取前cnt件,那么一定是cnt件情况下,花费最少的。
然后呢,n~1e5,s~1e9,暴力说到底,勉强能过,因为cnt×下标和,达到了cnt^3,所以件数不会超过1e3;
不难想到,价格总和 正相关于 cnt,所以二分,查找即可
 1 #include <bits/stdc++.h>
 2 using namespace std;
 3 typedef long long LL;
 4 
 5 const int N=1e5+5;
 6 int n,s,a[N];
 7 LL b[N];
 8 
 9 LL check(int m)
10 {
11     for(int i=1; i<=n; i++)
12         b[i]=a[i]+1LL*i*m;
13     sort(b+1,b+n+1);
14     LL ret=0;
15     for(int i=1; i<=m; i++)
16         ret+=b[i];
17     return ret;
18 }
19 
20 int main()
21 {
22     scanf("%d%d",&n,&s);
23     for(int i=1; i<=n; i++)
24         scanf("%d",&a[i]);
25     int l=0,r=n;
26     while(l<=r)
27     {
28         int m=(l+r)/2;
29         if(check(m)<=1LL*s) l=m+1;
30         else r=m-1;
31     }
32     printf("%d %lld",l-1,check(l-1));
33     return 0;
34 }

 

 

Codeforces 417 Div.2