NOIP模拟 17.8.16

NOIP模拟17.8.16

A 债务
文件名 输入文件 输出文件 时间限制 空间限制
debt.pas/c/cpp debt.in debt.out 1s 128MB
【题目描述】
小 G 有一群好朋友,他们经常互相借钱。假如说有三个好朋友 A,B,C。A
欠 B 20 元,B 欠 C 20 元,总债务规模为 20+20=40 元。小 G 是个追求简约的人,
他觉得这样的债务太繁杂了。他认为,上面的债务可以完全等价为 A 欠 C 20 元,
B 既不欠别人,别人也不欠他。这样总债务规模就压缩到了 20 元。
现在给定 n 个人和 m 条债务关系。小 G 想找到一种新的债务方案,使得每个
人欠钱的总数不变,或被欠钱的总数不变(但是对象可以发生变化),并且使得总
债务规模最小。
【输入格式】
输入文件第一行两个数字 n, m,含义如题目所述。
接下来 m 行,每行三个数字 ai
, bi, ci,表示 ai 欠 bi 的钱数为 ci。
注意,数据中关于某两个人 A 和 B 的债务信息可能出现多次,将其累加即可。
如”A 欠 B 20 元”、”A 欠 B 30 元”、”B 欠 A 10 元”,其等价为”A 欠 B 40 元”。
【输出格式】
输出文件共一行,输出最小的总债务规模。
【样例输入 1】
5 3
1 2 10
2 3 1
2 4 1
【样例输出 1】
10
【样例输入 2】
4 3
1 2 1
2 3 1
3 1 1
【样例输出 2】
0
【数据范围】
对于 30% 的数据,1 ≤ n ≤ 10,1 ≤ m ≤ 10。
对于 60% 的数据,1 ≤ n ≤ 100, 1 ≤ m ≤ 104。
对于 80% 的数据,1 ≤ n ≤ 104,1 ≤ m ≤ 104。
对于 100% 的数据,1 ≤ n ≤ 106,1 ≤ m ≤ 106。
对于所有的数据,保证 1 ≤ ai, bi ≤ n, 0 < ci ≤ 100。

【题解】

水题,略,注意细节,想清楚

 

 1 #include <cstdio>
 2 #include <cstdlib>
 3 #include <cstring>
 4 #include <iostream>
 5 
 6 const int MAXN = 100 + 10;
 7 
 8 inline void read(int &x)
 9 {
10     x = 0;char ch = getchar(), c = ch;
11     while(ch < '0' || ch > '9')c = ch, ch = getchar();
12     while(ch <= '9' && ch >= '0')x = x * 10 + ch - '0', ch = getchar();
13     if(c == '-')x = -x;
14 }
15 
16 char s[MAXN][MAXN];int n, ok;
17 
18 int check(int x, int y)
19 {
20     if(s[x][y] == '.')return 0;
21     if(x == n || x == n - 1)return 1;
22     if(y == 1 || y == n)return 1;
23     if(s[x + 1][y] == '.' || s[x + 2][y] == '.' || s[x + 1][y - 1] == '.' || s[x + 1][y + 1] == '.')return 1;
24     s[x][y] = s[x + 1][y] = s[x + 2][y] = s[x + 1][y - 1] = s[x + 1][y + 1] = '.';
25     return 0;
26 }
27 
28 int main()
29 {
30     read(n);
31     for(register int i = 1;i <= n;++ i) scanf("%s", s[i] + 1);
32     for(register int i = 1;i <= n;++ i)
33     {
34         for(register int j = 1;j <= n;++ j)
35             if(check(i, j))
36             {
37                 ok = 1;
38                 break;
39             }
40         if(ok)break;
41     }
42     if(ok)printf("NO");
43     else printf("YES");
44     return 0;
45 }
T1

 

 

 

B 小 Z 搭积木
文件名 输入文件 输出文件 时间限制 空间限制
box.cpp box.in box.out 2s 128MB
【题目描述】
小 Z 喜欢搭积木。小 Z 一共有 n 块积木,并且积木只能竖着一块一块的摞,可
以摞多列。小 Z 的积木都是智能积木,第 i 块积木有一个情绪值 Xi。当摞在该积
木上面积木总数超过 Xi 时,i 号积木就会不高兴。小 Z 情商这么高,肯定不希望
有积木不高兴。但是他又希望每块积木都被用上,并且摞的积木列的总数最少。你
能帮帮萌萌的小 Z 吗?
【输入格式】
输入文件第一行一个数字 n,含义如题目所述。
第 2 行一共 n 个数,第 i 个数为 Xi,含义如题目所述。
【输出格式】
输出一个数字,表示最小的积木列数目。
【样例输入 1】
3
0 0 10
【样例输出 1】
2
4
【样例输入 2】
4
0 0 0 0
【样例输出 2】
4
【数据范围】
30% 数据,1 ≤ n ≤ 10
60% 数据,1 ≤ n ≤ 100
80% 数据,1 ≤ n ≤ 1000
100% 数据,1 ≤ n ≤ 5000
对于所有数据点,都有 Xi ≤ n

 

【题解】

我的方法是二分答案降序贪心放。

标解是这样的:

先将所有的盒子按照承载量从小到大排序。然后我们开一个数组,

记录一下当前一共有多少列,每一列一共有多少个盒子。从小到

大扫描所有的盒子,找到能放下的数量最多的列,放进去。如果没

有任何一列能放下,则建一个新列。 ——SD Ag爷 ty哥哥

#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <iostream>
#include <algorithm>
#define min(a, b) ((a) < (b) ? (a) : (b))

const int MAXN = 5000 + 10;

inline void read(int &x)
{
    x = 0;char ch = getchar(), c = ch;
    while(ch < '0' || ch > '9')c = ch, ch = getchar();
    while(ch <= '9' && ch >= '0')x = x * 10 + ch - '0', ch = getchar();
    if(c == '-')x = -x;
}

int n, x[MAXN], ans, cnt[MAXN];

int check(int now)
{
    memset(cnt, 0x3f, sizeof(cnt));
    int p = 1, ok = 1;
    while(p <= n)
    {
        ok = 1;
        for(register int i = 1;i <= now;++ i)
        {
            if(!cnt[i])continue;
            cnt[i] = min(cnt[i] - 1, x[p]), ++p, ok = 0;
        }
        if(ok)return 0;
    }
    return 1;
}

int main()
{
    read(n);
    for(register int i = 1;i <= n;++ i) read(x[i]);
    std::sort(x + 1, x + 1 + n, std::greater<int>());
    register int l = 1, r = n, mid;
    while(l <= r)
    {
        mid = ((l + r) >> 1);
        if(check(mid))r = mid - 1;
        else l = mid + 1;
    } 
    printf("%d", l);
    return 0;
}
T2

C 分宿舍
文件名 输入文件 输出文件 时间限制 空间限制
love.cpp love.in love.out 1s 128MB
【题目描述】
A 校有着神奇的住宿制度,不分男女宿舍,所有 n 个学生被统一分到两栋宿舍
楼中。作为年轻人,学生之间心生爱慕之情是很正常。我们用爱慕值来表示两名学
生之间的爱慕程度,如果两名爱慕值为 c 的学生被安排在同一宿舍楼,他们或她们
便会在一起,并造成影响力为 c 的早恋事件。
每年年末,身为政教处主任的你会将所有早恋事件按照影响力从大到小排成一
个列表,然后上报给校长。公务繁忙的校长只会去看列表中第一个事件的影响力,
如果影响很大,他会考虑撤换政教处主任。
在详细考察了 n 个学生之间的爱慕关系后,你觉得压力很大。你要合理的将学
生们分到两栋宿舍,以求产生的早恋事件影响力都比较小,以保住自己的官职。假
设只要处于同一栋宿舍楼的两个人之间有爱慕关系,他们就一定会在这年的某个时
候在一起。
那么,要怎么分配,才能让校长看到的那个早恋事件的影响力最小呢?这个最
小值是多少?
【输入格式】
第一行两个整数 n 和 m,分别表示学生的数目和爱慕关系的对数。
接下来 m 行,每行为 3 个正整数 ai,bi,ci,表示学生 ai 和 bi 之间有爱慕关
系,爱慕值为 ci。
数据保证 1 ≤ ai ≤ bi ≤ n,0 < ci ≤ 109,且每对爱慕关系只出现一次。
【输出格式】
输出一个数,为通过合理安排,校长看到的那个早恋事件的最小影响力。如果
没有发生早恋事件,输出 0。
6
【样例输入】
4 6
1 4 2534
2 3 3512
1 2 28351
1 3 6618
2 4 1805
3 4 12884
【样例输出】
3512
【数据范围】
对于 30% 的数据,n ≤ 15。
对于 70% 的数据,n ≤ 2000,m ≤ 50000。
对于 100% 的数据,n ≤ 20000,m ≤ 100000。

【题解】

并查集裸题。

1. 普通并查集
i表示第i个学生,i+n为虚拟节点,表示不能和i在一个宿舍的人
若两个点在同一并查集中,说明它们必须被分到同一个宿舍楼
将所有的爱慕关系从大到小排序
若a和b在同一并查集中,则此时c为答案
若不在同一并查集,令a与b+n所在并查集合并,b与a+n所在并查集合并
2. 加权并查集
同样将所有爱慕关系从大到小排序
每个点存储额外信息type,type为0表示和父亲结点在同一个宿舍楼,1表示和父亲结点不在同一个宿舍楼
合并与查询的方式类似食物链

3. 二分+dfs
二分答案
对于比二分答案大的爱慕关系,建图,显然若该图可以黑白染色,该答案可行;反之不可行

——gty

 1 #include <cstdio>
 2 #include <cstdlib>
 3 #include <cstring>
 4 #include <iostream>
 5 #include <algorithm>
 6 
 7 const int MAXN = 20000 + 10;
 8 
 9 inline void read(int &x)
10 {
11     x = 0;char ch = getchar(), c = ch;
12     while(ch < '0' || ch > '9')c = ch, ch = getchar();
13     while(ch <= '9' && ch >= '0')x = x * 10 + ch - '0', ch = getchar();
14     if(c == '-')x = -x;
15 }
16 
17 int n,m,fa[MAXN << 2],a[MAXN],b[MAXN],c[MAXN],cnt[MAXN];
18 
19 int find(int x)
20 {
21     return x == fa[x] ? x : fa[x] = find(fa[x]);
22 } 
23 
24 int cmp(int a, int b)
25 {
26     return c[a] > c[b];
27 }
28 
29 int main()
30 {
31     read(n), read(m);
32     register int tmp1, tmp2, tmp3, p1, p2, pp1, pp2;
33     for(register int i = (n << 1);i >= 1;-- i)fa[i] = i;
34     for(register int i = 1;i <= m;++ i)read(a[i]), read(b[i]), read(c[i]), cnt[i] = i;
35     std::sort(cnt + 1, cnt + 1 + m, cmp);
36     for(register int i = 1;i <= m;++ i)
37     {
38         tmp1 = a[cnt[i]], tmp2 = b[cnt[i]], tmp3 = c[cnt[i]];
39         p1 = find(tmp1 << 1), p2 = find(tmp2 << 1);
40         pp1 = find(tmp1 << 1 | 1), pp2 = find(tmp2 << 1 | 1);
41         if(pp1 == pp2)
42         {
43             printf("%d", tmp3);
44             return 0;
45         }
46         fa[pp2] = p1;
47         fa[pp1] = p2;
48     }
49     printf("0");
50     return 0;
51 }
T3

 

转载于:https://www.cnblogs.com/huibixiaoxing/p/7375194.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值