Codeforces Round #460 (Div. 2)(A,B,C,D)

A. Supermarket

题目大意:给你n个超市蔬菜和水果的价格,ai,bi代表你可以花ai元买bi千克的蔬菜和水果,要你找出最便宜的那种买m千克蔬菜和水果;

题目思路:水题~用一个变量找出最小的ai/bi再乘上m即可;

代码如下:

#include <bits/stdc++.h>
using namespace std;
typedef long long LL;

int main(){
    int n,m;
    scanf("%d%d",&n,&m);
    double ans = 10000;
    for(int i = 0;i < n;i++){
        double a,b;
        scanf("%lf%lf",&a,&b);
        ans = min(ans,a/b);
    }
    printf("%.8f\n",ans*m);
    return 0;
}
B. Perfect Number

题目大意:要你求出满足各位的值加起来等于10的第k大的数;

题目思路:k最大是10000,而且cf的测试数据是单组的,所以你可以直接暴力求出第k个,当然也可以选择打表,也是一个水题~

(打表)代码如下:

#include <bits/stdc++.h>
using namespace std;
const int MX = 1e4+7;
typedef long long LL;

LL ans[MX];
int pcnt;

void init(){
    pcnt = 0;
    for(int i = 19;i < 11000000;i++){
        if(pcnt >= MX-1) break;
        int tmp = i;
        int sum = 0;
        while(tmp){
            sum += tmp%10;
            tmp/=10;
        }
        if(sum == 10){
            ans[++pcnt] = i;
        }
    }
}


int main(){
    init();
    int n;cin >> n;
    cout << ans[n] << endl;
    return 0;
}
C. Seat Arrangements

题目大意:在一个n*m的教室里,‘*’表示当前座位已经有人,‘.’表示没有人,要你找出连续(同一行或者同一列)的k个座位,问你一共有多少种不同的方式;

题目思路:暴力找即可,先找行,再找列,要注意就是如果有连续p(p >= k)个空座位,那么就有p-k+1种方式,这样我们每次找的时候都成段的移动就可以大大减少时间复杂度,要特别注意的是当k = 1时只用找一遍就行了;

代码如下:

#include <bits/stdc++.h>
using namespace std;

int n, m, k;
char mp[2005][2005];

int main() {
    scanf("%d%d%d", &n, &m, &k);
    for(int i = 0; i < n; i++) scanf("%s", mp[i]);
    int ans = 0;
    for(int i = 0; i < n; i++) {
        for(int j = 0; j < m; j++) {
            if(mp[i][j] == '.') {
                int p;
                for(p = 0;; p++) {
                    if(mp[i][p + j] != '.') break;
                }
                if(p >= k){ 
                    ans += p-k+1;
                }
                j += p;
            }
        }
    }
    if(k > 1) {
        for(int j = 0; j < m; j++) {
            for(int i = 0; i < n; i++) {
                if(mp[i][j] == '.') {
                    int p;
                    for(p = 0;; p++) {
                        if(mp[i + p][j] != '.') break;
                    }
                    if(p >= k){ 
                        ans += p-k+1;
                    }
                    i += p;
                }
            }
        }
    }
    printf("%d\n", ans);
    return 0;
}

D. Substring

题目大意:在一个由n个点和m条边组成的有向图中,每个节点都有一个字母,要你找出在所有可行路径中单条路径出现次数最多的那个字母出现了几次,如果有个字母出现了无限次那么就输出“-1”;

题目思路:如果一个字母出现了无限次,那么一定是图中出现环了(一个环的可行路径就是无限的),因为这是个有向图,那么我们就可以直接用拓扑排序来找环,而要统计出现次数最多的字母的话,我们可以设dp[i][j]表示在 i 这个节点中 j 这个字母最多出现了几次,那么就可以得到

dp[i][j] = max(dp[i][j],dp[u][j]),u 是 i 的父亲节点;

最后再统计一下最大的是多少就行了;

代码如下:

#include <bits/stdc++.h>
using namespace std;
const int MX = 3e5+7;

int n,m;
int in[MX],dp[MX][30];
char str[MX];
vector<int>E[MX];

int dfs(){
    queue<int>q;
    int cnt = 0;
    for(int i = 1;i <= n;i++){
        if(!in[i]){
            q.push(i);
        }
    }
    while(!q.empty()){
        int u = q.front();q.pop();
        cnt++;
        dp[u][str[u]-'a']++;
        for(auto v : E[u]){
            if(--in[v] == 0){
                q.push(v);
            }
            for(int j = 0;j < 26;j++)
                dp[v][j] = max(dp[v][j],dp[u][j]);
        }
    }
    if(cnt != n) return 0;
    return 1;
}

int main(){
    scanf("%d%d",&n,&m);
    scanf("%s",str+1);
    for(int i = 0;i < m;i++){
        int u,v;scanf("%d%d",&u,&v);
        E[u].push_back(v);
        in[v]++;
    }
    int flag = dfs();
    if(!flag) puts("-1");
    else{
        int ans = 0;
        for(int i = 1;i <= n;i++){
            for(int j = 0;j < 26;j++)
                ans = max(ans,dp[i][j]);
        }
        printf("%d\n",ans);
    }
    return 0;
}
E和F暂时做不出来(可能短时间内也做不出来。。。),等我会了再更新吧 -,-

猜你喜欢

转载自blog.csdn.net/lee_w_j__/article/details/79234296