您的位置:首页 > 其它

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

2016-10-30 21:46 495 查看

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);
}
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: 
相关文章推荐