Codeforces Round #374 (Div. 2)解题报告

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Codeforces Round #374 (Div. 2)解题报告相关的知识,希望对你有一定的参考价值。

Problem B: Passwords

题意:给出n个字符串密码,在给出一个正确密码,输密码必须先输入简单的密码,连续输错k次密码会罚时5秒,输一次密码耗时1秒,求可能的最短和最长的耗时。(注意:给出的n个密码可能包含多个正确密码)

思路:略

code:

技术分享
#include <map>
#include <set>
#include <queue>
#include <stack>
#include <vector>
#include <cstdio>
#include <cmath>
#include <cstdlib>
#include <ctime>
#include <cstring>
#include <iostream>
#include <algorithm>
#define rep(i,k,n) for(int i = k;i < n;i ++)
#define repp(i,k,n) for(int i = k;i <= n;i ++)
#define scan(d) scanf("%d",&d)
#define scanl(d) scanf("%I64d",&d)
#define scann(n,m) scanf("%d %d",&n,&m)
#define scannl(n,m) scanf("%I64d %I64d",&n,&m)
#define mst(a,k)  memset(a,k,sizeof(a))
#define mod 1e9+7
#define ll long long
#define maxn 105
using namespace std;
int cnt[maxn];
map<string,int> mmap;
string p,s;
int main(void){
    int n,k;
    cin >> n >>k;
    mst(cnt,0);
    mmap.clear();
    for(int i = 1;i <= n;i ++){
        cin >> p;
        mmap[p] ++;
        cnt[p.size()] ++;
    }
    cin >> s;
    int len = s.size();
    int cnt1,cnt2;
    cnt1 = cnt2 = 0;
    for(int i = 1;i <= len - 1;i ++){
        cnt1 += cnt[i];
    }
    cnt2 += cnt[len];
    cnt2 -= (mmap[s]);
    int ans1,ans2;
    ans1 = (cnt1/k)*5 + 1 + cnt1;
    ans2 = ((cnt1 + cnt2)/k)*5 + cnt1 + cnt2 + 1;
    printf("%d %d\\n",ans1,ans2);
    return 0;
}
View Code

Problem C: Journey

题意:给出一个有n个节点的有向图,每条路包含一个权值表示走过这条路的时间,要求在给出的总时间T内必须从起点1走到终点n,求在满足条件的情况下,走过节点数的最大值。

思路:dfs + dp。dp[i][t]表示走到第i个节点路过节点数为t时使用的最小时间的,则dp[i][t] = min(dp[k][t-1]+t[k][i],dp[i][t])。

code:

技术分享
#include <map>
#include <set>
#include <queue>
#include <stack>
#include <vector>
#include <cstdio>
#include <cmath>
#include <cstdlib>
#include <ctime>
#include <cstring>
#include <iostream>
#include <algorithm>
#define rep(i,k,n) for(int i = k;i < n;i ++)
#define repp(i,k,n) for(int i = k;i <= n;i ++)
#define scan(d) scanf("%d",&d)
#define scanl(d) scanf("%I64d",&d)
#define scann(n,m) scanf("%d %d",&n,&m)
#define scannl(n,m) scanf("%I64d %I64d",&n,&m)
#define mst(a,k)  memset(a,k,sizeof(a))
#define mod 1e9+7
#define inf 2000000005
#define ll long long
#define maxn 5005
using namespace std;
int edgesCnt;
int head[maxn];
int fa[maxn][maxn];     //fa[i][j]表示走到第i个节点时走过了j个节点时的前驱
int dp[maxn][maxn];     //dp[i][t]表示走到第i个节点路过节点数为t时使用的最小时间的,则dp[i][t] = min(dp[k][t-1]+t[k][i],dp[i][t])。
int n,m,Tot;
struct Edge{
    int to;
    int dist;
    int next;
}edges[maxn];
void init(){
    edgesCnt = 0;
    memset(head,-1,sizeof(head));
}
void addEdge(int from,int to,int d){
    edges[edgesCnt].dist = d;
    edges[edgesCnt].to = to;
    edges[edgesCnt].next = head[from];
    head[from] = edgesCnt;
    edgesCnt ++;
}
void dfs(int u,int step){
    for(int j = head[u];j != -1;j = edges[j].next){
        int v = edges[j].to;
        int d = edges[j].dist;
        if(dp[v][step+1] > dp[u][step]+d && dp[u][step]+d <= Tot){
            dp[v][step+1] = dp[u][step]+d;
            fa[v][step+1] = u;
            dfs(v,step+1);
        }
    }
}
//递归输出路径
void print(int u,int j){
    if(u == 1) {
            printf("1 ");
            return;
    }
    else{
        print(fa[u][j],j-1);
    }
    printf("%d ",u);
    if(u == n)
        printf("\\n");
}
int main(void){

    cin >> n >> m >> Tot;
    init();
    for(int i = 1;i <= m;i ++){
        int u,v,d;
        scanf("%d %d %d",&u,&v,&d);
        addEdge(u,v,d);
    }
    for(int i = 1;i <= n+1;i ++){
        for(int j = 1;j <= n+1;j ++){
            dp[i][j] = inf;
        }
    }
    dp[1][1] = 0;
    dfs(1,1);
    for(int i = n;i >= 1;i --){
            if(dp[n][i] <= Tot){
                printf("%d\\n",i);
                print(n,i);
                return 0;
            }
    }
    return 0;
}
View Code

Problem D: Maxim and Array

题意:给出一个包含n个数的数组,给出一个整数x,执行k次操作(对数组任意一个元素加x或减x)。求数组的积最小。

思路:若数组的积的符号是负,则每次操作只需要对绝对值最小的元素执行操作;若数组的积是正,则同样是最绝对值最小的元素进行操作,目的是尽快实现变号,若无法变号,也可以使积变小。综上,只需使用优先队列处理至多k次操作即可。

code:

技术分享
#include <map>
#include <set>
#include <queue>
#include <stack>
#include <vector>
#include <cstdio>
#include <cmath>
#include <cstdlib>
#include <ctime>
#include <cstring>
#include <iostream>
#include <algorithm>
#define rep(i,k,n) for(int i = k;i < n;i ++)
#define repp(i,k,n) for(int i = k;i <= n;i ++)
#define scan(d) scanf("%d",&d)
#define scanl(d) scanf("%I64d",&d)
#define scann(n,m) scanf("%d %d",&n,&m)
#define scannl(n,m) scanf("%I64d %I64d",&n,&m)
#define mst(a,k)  memset(a,k,sizeof(a))
#define mod 1e9+7
#define ll long long
#define maxn 200005
using namespace std;
ll a[maxn];
ll n,k,x;
int flag;
struct node{
    int id;
    ll value;
    bool flag;         //状态,1代表正,0代表负
    bool operator < (const node& rhs) const{
        return value > rhs.value;
    }
};
int main(void){
    while(cin >> n >> k >> x){
        priority_queue<node> Q;
        //Q.clear();
        while(!Q.empty()) Q.pop();
        int cnt = 0;
        for(int i = 1;i <= n;i ++) {
            cin >> a[i];
            node p;
            if(a[i] < 0) {
                cnt ++;
                p.value = abs(a[i]);
                p.flag = 0;
                p.id = i;
                Q.push(p);
            }
            else{
                p.value = abs(a[i]);
                p.flag = 1;
                p.id = i;
                Q.push(p);
            }
        }
        flag = cnt%2?-1:1;
        ll sum = x*k;
        while(k){
            node tp = Q.top();
            Q.pop();
            ll id,value,f;
            id = tp.id;
            value = tp.value;
            f = tp.flag;
            if(flag == 1){    //符号为正
                if(sum > value){
                    a[id] -= f == 1?(value/x)*x:(-value/x)*x;
                    k -= (value/x);
                    sum = k*x;
                    if(a[id] >= 0 && f == 1) {a[id] -= x; k --; sum -= x;}
                    if(a[id] < 0 && f == 0) {a[id] += x; k --; sum -= x;}
                    flag = -1;
                    node p;
                    p.flag = f == 1?0:1;
                    p.id = id;
                    p.value = abs(a[id]);
                    Q.push(p);
                }
                else{
                    a[id] -= f == 1?sum:-sum;
                    k = sum = 0;
                }
            }
            else{            //符号为负
                a[id] += f == 1?x:-x;
                k --;
                sum -= x;
                node p;
                p.flag = f == 1?1:0;
                p.id = id;
                p.value = abs(a[id]);
                Q.push(p);
            }
        }
        for(int i = 1;i <= n;i ++) printf("%I64d ",a[i]);
        cout << endl;
    }
    return 0;
}
View Code

 

以上是关于Codeforces Round #374 (Div. 2)解题报告的主要内容,如果未能解决你的问题,请参考以下文章

Codeforces Round #374(div 2)

Codeforces Round #374 (Div. 2)解题报告

Codeforces Round #374 (Div. 2)

Codeforces Round #374 (Div. 2)-C. Journey DP

Codeforces Round #374 (Div. 2) D. Maxim and Array

Codeforces Round #374 (Div. 2)-D Maxim and Array