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;
}

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;
}

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;
}

时间: 2024-10-12 02:47:06

Codeforces Round #374 (Div. 2)解题报告的相关文章

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

终于重上DIV1了.... A:在正方形中输出一个菱形 解题代码: 1 // File Name: a.cpp 2 // Author: darkdream 3 // Created Time: 2014年08月01日 星期五 23时27分55秒 4 5 #include<vector> 6 #include<set> 7 #include<deque> 8 #include<stack> 9 #include<bitset> 10 #inclu

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

详见:http://robotcator.logdown.com/posts/221514-codeforces-round-262-div-2 1:A. Vasya and Socks   http://codeforces.com/contest/460/problem/A 有n双袜子,每天穿一双然后扔掉,每隔m天买一双新袜子,问最多少天后没有袜子穿.. 简单思维题:以前不注重这方面的训练,结果做了比较久,这种题自己边模拟边想.不过要多考虑trick ```c++ int main(){ i

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

Codeforces Round #616 (Div. 2)解题报告 A. Even But Not Even 找两个奇数就行了. #include<bits/stdc++.h> using namespace std; void solve() { int n; string s; cin >> n >> s; string ans = ""; for(int i = 0; i < n; i++) { if(int(s[i] - '0')%2

Codeforces Round #479 (Div. 3)解题报告

题目链接: http://codeforces.com/contest/977 A. Wrong Subtraction 题意 给定一个数x,求n次操作输出.操作规则:10的倍数则除10,否则减1 直接写,手速题,没啥好说的 B. Two-gram 题意 求出现次数最多的连续两个字符 还是签到题,我居然很麻烦地用了map,= =算了,思路畅通都无所谓了 #include <iostream> #include<stdio.h> #include<algorithm> #

Codeforces Round #515 (Div. 3) 解题报告(A~E)

题目链接:http://codeforces.com/contest/1066 A题: 题意:Vova想坐火车从1点到L点,在路上v的整数倍的点上分布着灯笼,而在路上从l到r处停着别的火车,它挡着Vova的视线使他看不到灯笼.给定L,v,l,r求Vova能看到的灯笼数. 分析:从1到x上所有的灯笼数量为x/v个.则路上所有的灯笼数为L/v个,被挡住的则为 r/v - (l-1)/v 个,相减即为答案. #include<iostream> #include<cstdio> #inc

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

A - Shell Game 1 #include <iostream> 2 #include<bits/stdc++.h> 3 #include <stack> 4 #include <queue> 5 #include <map> 6 #include <set> 7 #include <cstdio> 8 #include <cstring> 9 #include <algorithm> 10

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

时隔一个月重返coding…… 期末复习了一个月也不亏 倒是都过了…… 就是计组61有点亏 复变68也太低了 其他都还好…… 假期做的第一场cf 三道题 还可以…… 最后room第三 standing383简直人生巅峰…… 看楼上楼下都是两道题的 如果A题不错那么多估计能进前300了吧…… 这场倒是把之前两场的分加回来了 开头不错 这个假期争取紫名~ A.Lesha and array splitting 把给定的数组分割成几个区间 要求各个区间和不能为0 一开始没注意到分割之后的区间重新合成之

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

开始补题,今天下午virtual参赛,过了ABC,D题因为一点小错误而没能在比赛时间中AC,时间到了之后几分钟就发现了问题所在,略有遗憾.之后一直冥思苦想E题,在提示下终于明白,真的是给这样组合题画风的题目跪了,只能说继续加油,扩展思路吧. A题 题目地址 只有奇偶数个数相差小于等于1时可以,需要特判不能使二者均为0的情况. 参考代码 1 #include<stdio.h> 2 #include<bits/stdc++.h> 3 #include <iostream>

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

A - Team Olympiad 贪心水题..都从第一个开始取即可. 代码如下: #include <iostream> #include <cstdio> #include <string> #include <cstring> #include <stdlib.h> #include <math.h> #include <ctype.h> #include <queue> #include <map