2016年中国大学生程序设计竞赛(杭州)

hdu ArcSoft’s Office Rearrangement

这道题做了好久未果,我感觉好难,为啥好多人都做出来了,自己就很气,发现自己发现合并只能与相邻的砖块合并,好气呀!!赛后补题用了2种方法去做它用于解气。
第一种方法纯模拟,如果当前值大于平均值直接分裂,多余的部分给右边,因为是从左往右进行的。注意用long long,不然估计又要哭一天!!!

#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
using namespace std;
const int maxn = 1e5+10;
#define LL long long
LL a[maxn];

int main(){
    LL T, N, K;
    scanf("%I64d", &T);
    for(int kase = 1; kase <= T; kase++){
        scanf("%I64d%I64d", &N, &K);
        LL sum = 0;
        for(int i = 0; i < N; i++){
            scanf("%I64d", &a[i]);
            sum += a[i];
        }
        printf("Case #%d: ", kase);
        if(sum%K) printf("-1\n");
        else{
            LL ans = 0;
            sum /= K;
            for(int i = 0; i < N; i++){
                if(a[i] > sum){
                    if(a[i]%sum){
                        ans += (a[i]/sum)+1;
                        a[i+1] += a[i]%sum;
                    }
                    else ans += (a[i]/sum)-1;
                }
                else if(a[i] < sum){
                    a[i+1] += a[i];
                    ans++;
                }

            }
            printf("%I64d\n", ans);
        }
    }
    return 0;
}

另一种方法就是求前缀和的思想,如果成立那么我们就可以减少合并或者分裂的次数,给出代码。

#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
using namespace std;
const int maxn = 1e5+10;
#define LL long long
LL a[maxn];

int main(){
    LL T, N, K;
    scanf("%I64d", &T);
    for(int kase = 1; kase <= T; kase++){
        scanf("%I64d%I64d", &N, &K);
        LL sum = 0;
        for(int i = 0; i < N; i++){
            scanf("%I64d", &a[i]);
            sum += a[i];
        }
        printf("Case #%d: ", kase);
        if(sum%K) printf("-1\n");
        else{
            LL ans = 0;
            sum /= K;
            for(int i = 0; i < N; i++){
                if(a[i] > sum){
                    if(a[i]%sum){
                        ans += (a[i]/sum)+1;
                        a[i+1] += a[i]%sum;
                    }
                    else ans += (a[i]/sum)-1;
                }
                else if(a[i] < sum){
                    a[i+1] += a[i];
                    ans++;
                }

            }
            printf("%I64d\n", ans);
        }
    }
    return 0;
}

hdu 5934 Bomb

强连通分量的题目,先缩点,然后处理,对于每一个缩点求出入度,然后入度为0的地方一定要引爆,如果入度为0的地方是一个有多个顶点的强连通分量则求最小值,注意用long long,不然算距离的时候会爆炸,又要在厕所哭一年!!!

#include <cmath>
#include <cstdio>
#include <vector>
#include <cstring>
#include <iostream>
#include <algorithm>
using namespace std;
const int maxn = 1005;
#define LL long long

struct Node{
    LL x, y, r, c;
}node[maxn];

int n;
vector <int> G[maxn];
vector <int> rG[maxn];
vector <int> vs;
bool used[maxn];
int cmp[maxn], degree[maxn], vis[maxn][maxn];

void addedge(int from, int to){
    G[from].push_back(to);
    rG[to].push_back(from);
}

void dfs(int v){  //正向建边给所有节点设置一个标号
    used[v] = true;
    for(int i = 0; i < G[v].size(); i++)
        if(!used[G[v][i]]) dfs(G[v][i]);
    vs.push_back(v);
}

void rdfs(int v, int k){
    used[v] = true;
    cmp[v] = k;
    for(int i = 0; i < rG[v].size(); i++)
        if(!used[rG[v][i]]) rdfs(rG[v][i], k);
}

int scc(){
    memset(used, 0, sizeof(used));
    vs.clear();
    for(int v = 0; v < n; v++)  // 给所有节点进行编号
        if(!used[v]) dfs(v);
    memset(used, 0, sizeof(used));
    int k = 0;
    for(int i = vs.size()-1; i >= 0; i--)  //通过反向边来跑找到强连通分量
        if(!used[vs[i]]) rdfs(vs[i], k++);
    return k; //k表示有多少强连通分量
}

void init(){
    memset(degree, 0, sizeof(degree));
    memset(vis, 0, sizeof(vis));
    for(int i = 0; i < maxn; i++)
        G[i].clear(), rG[i].clear();
}

int main(){
    int T;
    scanf("%d", &T);
    for(int kase = 1; kase <= T; kase++){
        init();
        scanf("%d", &n);
        for(int i = 0; i < n; i++)
            scanf("%I64d%I64d%I64d%I64d", &node[i].x, &node[i].y, &node[i].r, &node[i].c);
        for(int i = 0; i < n; i++){
            for(int j = i+1; j < n; j++){
                double dis = sqrt((LL)(node[i].x-node[j].x)*(node[i].x-node[j].x)+(LL)(node[i].y-node[j].y)*(node[i].y-node[j].y));
                if(node[i].r >= dis) addedge(i, j), vis[i][j] = 1;
                if(node[j].r >= dis) addedge(j, i), vis[j][i] = 1;
            }
        }
        int k = scc();
        for(int i = 0; i < n; i++){
            for(int j = 0; j < n; j++){
                if(!vis[i][j] || cmp[i] == cmp[j]) continue;
                degree[cmp[j]]++;
            }
        }
        int ans = 0;
        for(int i = 0; i < k; i++){
            if(degree[i] == 0){
                int temp = 1e5;
                for(int j = 0; j < n; j++)
                    if(cmp[j] == i) if(node[j].c < temp) temp = node[j].c;
                ans += temp;
            }
        }
        printf("Case #%d: %d\n", kase, ans);
    }
    return 0;
}

hdu 5935 Car

从最后一个点向前处理,然后二分时间找速度,错了一下午!因为我用了单调队列去处理,结果死的比谁都惨!!

#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
using namespace std;
const int maxn = 1e5+100;
int a[maxn];

int main(){
    #ifdef LOCAL_BUG
        freopen("input.txt", "r", stdin);
    #endif // LOCAL_BUG
    int T, n;
    scanf("%d", &T);
    for(int kase = 1; kase <= T; kase++){
        scanf("%d", &n);
        for(int i = 1; i <= n; i++) scanf("%d", &a[i]);
        a[0] = 0;
        for(int i = 0; i < n; i++) a[i] = a[i+1] - a[i];
        double temp = a[n-1];
        int ans = 1;
        for(int i = n-2; i >= 0; i--){
            double x = a[i];
            int l = 1, r = 1e9;
            while(l < r){
                int mid = (l+r)/2;
                if(x/mid <= temp) r = mid;
                else l = mid+1;
            }
            ans += r;
            temp = x/r;
        }
        printf("Case #%d: %d\n", kase, ans);
    }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值