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

A - ArcSoft's Office Rearrangement HDU - 5933

题意:
给你n个数,你有两个操作:1.将相邻两个数合并 2.将一个数拆分成两个数
求将这n个数变成k个相同的数最小操作数。
思路
实际上要变为k个相同的数,每次的合并和分解都是必要的,那么可以直接先合并后分解。

#include <bits/stdc++.h>
//#pragma GCC optimize(3) //如果有STL,开O3
#define endl '\n'
#define pii pair<int,int>
#define int long long
using namespace std;

const int N = 1e5 + 10;
int t, n, k, a[N], cnt, sum,ans= 0, ave,tt, tot;

void solve(){
    cin >> t;
    while(t -- ){
        tt ++;
        cin >> n >> k;
        ans = 0;
        cnt = 0;
        for(int i = 1; i <= n; i++){
            cin >> a[i];
            ans += a[i];
        }
        sum = 0;
        if(ans % k == 0){
            ave = ans / k;
            for(int i = 1; i <= n; i++){
                sum += a[i];
                if(sum % ave == 0){
                    cnt += tot + (sum / ave - 1);
                    tot = 0;
                    sum = 0;
                }
                else{
                    tot ++;
                }
            }
            cout <<"Case #"<<tt<<": " <<cnt << endl;
        }
        else{
            cout <<"Case #"<<tt<<": " <<-1 << endl;
        }
    }
}

signed main()
{
    ios::sync_with_stdio(false);
    cin.tie(0);
    cout.tie(0);
    solve();
    return 0;
}

B - Bomb HDU - 5934 强连通分量tarjan

题意:
给出n个炸弹的坐标(x,y)、爆炸能辐射成一个圆的半径r和引爆该炸弹需要的代价c,
且某一个炸弹爆炸后,无需要代价直接引爆在能辐射圆内的炸弹,
问如何引爆所有炸弹需要的最小代价。
思路:
做题先是想到了dp,后来又想到了并查集,后来发现都解决不了。A可以引爆B但是,B不一定引爆A的问题。
后来想到了强连通分量:

  1. 将可以相互引爆的进行缩点;
    (因为无论选择谁都可以连环炸)
  2. 然后对缩后的点建立有向边;
    建立的图一定是棵树(或者是森林)
  3. 然后只需要选择所有树的根节点即可。
    因为是有向边,选择其他的点也需要再选择根节点,但是选择就可以连环炸掉他的所有子树。

代码:
错误代码(超时了)
超时原因:

  1. 写了一个check函数,因为check的参数是Node,调用时会很慢.....具体也不清楚队友说的。 下次注意了。
  2. 初始化时用的memset(x,0,sizeof x),每次会初始化整个数组
  3. 使用了函数pow
void init(){
}
struct  Node
{
  int x,y;
  int r,val;
}a[N];
bool check(Node q,Node p){
  int len=pow(abs(q.x-p.x),2)+pow(abs(q.y-p.y),2);
  if(len>(q.r*q.r)) return false;
  else return true;
}
void tarjan(int u){
}
int xxx;
void slove(){
}
signed main()
{
}

正确代码:

#include <iostream>
#include <algorithm>
#include <cstring>
#include <cmath>
using namespace std;
#define int long long
const int N = 1010;
const int M = 2e6 + 10;
int n;
int to[M], pre[M], h[N], idx;
int dfn[N], low[N], temp;
int id[N], scc_cnt, scc_size[N], scc_min[N];
int stk[N], top;
bool in_stk[N];
int d[N];
void init()
{
  for (int i = 0; i <= n; i++)
    h[i] = -1;
  for (int i = 0; i <= n; i++)
    scc_min[i] = 0x3f3f3f3f3f;
  for (int i = 0; i <= n; i++)
    in_stk[i] = false;
  for (int i = 0; i <= n; i++)
    d[i] = 0;
  for (int i = 0; i <= n; i++)
    dfn[i] = 0;
  for (int i = 0; i <= n; i++)
    low[i] = 0;
  top = 0;
  idx = 0;
  scc_cnt = 0;
  temp = 0;
}
struct Node
{
  int x, y;
  int r, val;
} a[N];
void add(int x, int y)
{
  to[idx] = y, pre[idx] = h[x], h[x] = idx++;
}
void tarjan(int u)
{

  dfn[u] = low[u] = ++temp;
  stk[++top] = u;
  in_stk[u] = true;
  for (int i = h[u]; i != -1; i = pre[i])
  {
    int j = to[i];
    if (!dfn[j])
    {
      tarjan(j);
      low[u] = min(low[u], low[j]);
    }
    else if (in_stk[j])
      low[u] = min(low[u], dfn[j]);
  }
  if (low[u] == dfn[u])
  {
    int y;
    scc_cnt++;
    do
    {
      y = stk[top--];
      in_stk[y] = false;
      id[y] = scc_cnt;
      scc_size[scc_cnt]++;
      scc_min[scc_cnt] = min(a[y].val, scc_min[scc_cnt]);
    } while (y != u);
  }
}
bool check(int i, int j)
{
  int len = (a[i].x - a[j].x) * (a[i].x - a[j].x) + (a[i].y - a[j].y) * (a[i].y - a[j].y);

  if (len > (a[i].r * a[i].r))
    return false;
  else
    return true;
}
int xxx;
void slove()
{
  cin >> n;
  init();
  for (int i = 0; i < n; i++)
  {
    cin >> a[i].x >> a[i].y >> a[i].r >> a[i].val;
  }
  for (int i = 0; i < n; i++)
  {
    for (int j = 0; j < n; j++)
    {
      if (i == j)
        continue;
      if (check(i, j))
        add(i, j);
    }
  }
  for (int i = 0; i < n; i++)
  {
    if (!dfn[i])
      tarjan(i);
  }
  for (int i = 0; i < n; i++)
  {
    for (int j = h[i]; j != -1; j = pre[j])
    {
      int y = to[j];
      if (id[i] != id[y])
        d[id[y]]++;
    }
  }
  int cnt = 0;

  for (int i = 1; i <= scc_cnt; i++)
  {
    if (!d[i])
    {
      cnt += scc_min[i];
    }
  }
  printf("Case #%lld: %lld\n", ++xxx, cnt);
}

signed main()
{
  int t;
  cin >> t;
  while (t--)
  {
    slove();
  }
  return 0;
}

C - Car HDU - 5935

题意:
车子从起始位置 0开始到达终点一共有 N 个位置被标记,每个位置被标记的时间都是整数时间,并且车子只能做加速运动和匀速运动。问,车子最短时间达到终点的时间花费。
思路:
逆向贪心模拟,最好一段肯定是一秒花费,根据这个速度来往前推,速度不严格递减,保证每段时间是整数。看代码吧

因为速度是小数,为了避免精度丢失,采用分数形式来表示。

代码

#include <iostream>
#include <algorithm>
#include <cstring>
#include <cmath>
using namespace std;
#define int long long
const int N = 1e5+10;
const int M = 2e6 + 10;
int n;
int a[N];
int case_=1;
void slove()
{
   scanf("%lld", &n);
   a[0]=0;
   for(int i=1;i<=n;i++){
          scanf("%lld", &a[i]);
   }
   int ans=1;
   int p=a[n]-a[n-1],q=1;

   for(int i=n-1;i>=1;i--){
       int dis=a[i]-a[i-1];
       q*=dis;
       swap(p,q);
       int t=ceil(1.0*p/q);
       ans+=t;

       p=dis,q=t;

   }

   printf("Case #%lld: %lld\n", case_++, ans);
}

signed main()
{
  int t;
   scanf("%lld", &t);
  while (t--)
    slove();

  return 0;
}

# F - Four Operations HDU - 5938
题意:

给你一个只有“1~9”数字的字符串,求按顺序插入“+”,“-”,“*”,“/”后,算式能够得到的最大值。
思路 贪心,看代码吧

#include <bits/stdc++.h>
//#pragma GCC optimize(3) //如果有STL,开O3
#define endl '\n'
#define pii pair<int,int>
#define int long long
using namespace std;

const int N = 1e5 + 10;
int t, ans, tt;

int max(int a, int b){
    if(a > b) return a;
    else return b;
}

void solve(){
    cin >> t;
    while(t -- ){
        string st;
       // st = "0";
       tt ++;
        cin >> st;
        if(st.size() == 5){
            cout <<"Case #"<<tt<<": ";
            cout << (st[0] -'0') + ( st[1] -'0') - (st[2] - '0') * (st[3] - '0') / (st[4] - '0') << endl;
        }
        else{
            int len = st.size() - 1;
            //last
            int s4 = st[len] - '0';
            int s3 = st[len - 1] - '0';
            int s2 = st[len - 2] - '0';
            int s1 = 0;
            if(len - 3 >= 2){
                int u = st[0] - '0';
                int v = 0;
                for(int i = 1; i <= len - 3; i ++){
                    v = v * 10 + (st[i] - '0');
                }
               // cout << u <<" - " << v << endl;
                s1 = u + v;
                //cout <<"?" << s1 << endl;
                u = st[len - 3] - '0';
                v = 0;
                for(int i = 0; i <= len - 4; i ++){
                    v = v * 10 + (st[i] - '0');
                }
                s1 = max(s1, u + v);
                ans = s1 - s2 * s3 / s4;
                // cout <<s1 <<" "<<s2 <<" " << s3 <<" "<<s4 <<endl;
                // cout << 1 <<" " << ans << endl;
            }
            else{
                s1 = st[0] -'0' + (st[1] - '0');
                ans = s1 - s2 * s3 / s4;
                //cout << 1 <<" " << ans << endl;
            }
            //last1
            s4 = (st[len - 1] - '0') * 10 + (st[len] - '0');
            s3 = st[len - 2] -'0';
            s2 = st[len - 3] - '0';
            if(len - 4 >= 2){
                int u = st[0] - '0';
                int v = 0;
                for(int i = 1; i <= len - 4; i ++){
                    v = v * 10 + (st[i] - '0');
                }
                s1 = u + v;
                u = st[len - 4] - '0';
                v = 0;
                for(int i = 0; i <= len - 5; i ++){
                    v = v * 10 + (st[i] - '0');
                }
                s1 = max(s1, u + v);
                ans = max(ans, s1 - s2 * s3 / s4);
                //cout << 2 <<" " << ans << endl;
            }
            else{
                s1 = st[0] -'0' + (st[1] - '0');
                ans = max(ans,s1 - s2 * s3 / s4);
                //cout << 2 <<" " << ans << endl;
            }
            cout <<"Case #"<<tt<<": " << ans << endl;
        }
    }
}

signed main()
{
    ios::sync_with_stdio(false);
    cin.tie(0);
    cout.tie(0);
    solve();
    return 0;
}
posted @ 2022-07-15 09:09  kingwzun  阅读(54)  评论(0编辑  收藏  举报