为了能到远方,脚下的每一步都不能少.|

Zac-saodiseng

园龄:2年4个月粉丝:3关注:0

ACM预备队-week6(贪心)

 [NOIP2010 普及组] 三国游戏

题目链接:P1199 [NOIP2010 普及组] 三国游戏 - 洛谷 | 计算机科学教育新生态 (luogu.com.cn)

就是考脑子,,小涵拿不到最大的默契值,同时计算机也拿不到,最大的那一对一定会被两方拆散,所以小涵每次可以拿到次大的最佳武将组合,记为(i,j),不妨设(i,k),(j,l)分别为两对最佳匹配。

第一步,小涵拿i,所以计算机一定拿k,第二步,小涵拿j,计算机一定拿l,所以小涵就拿到了次大中最佳匹配的组合(i,j),而因为默契值都不相同 ,并且(k,l)不是最佳次大,所以小涵的武将默契值比电脑高,即(i,j)>(k,l)。

之后,小涵只要不让计算机拿到剩余的所有最佳匹配,则计算机至多拿到次佳。已知次佳的最大一对在小涵手里,所以小涵必胜

因此,不能降成一维输出次大(20分),而是应该把每一行的次大取max,这才是最后答案

相当于:小涵选全图具有最大匹配值武将之一,然后计算机拆散了,然后小涵拿到了次大武将,并且与第一次选的匹配生成了最大默契,然后计算机把视角转向了第二次选的那一行,然后重新拆散这一行的最大值,所以小涵每次就挑着具有次大max的那一行挑,就必赢

 

复制代码
 1 #include <bits/stdc++.h>
 2 using namespace std;
 3 const int N=510;
 4 int a[N][N];
 5 int ans;
 6 int main()
 7 {
 8     ios::sync_with_stdio(false),cin.tie(0),cout.tie(0);
 9     int n;
10     cin>>n;
11     for(int i=1;i<n;i++)
12     for(int j=i+1;j<=n;j++)
13     {
14         cin>>a[i][j];
15         a[j][i]=a[i][j];
16     }
17     for(int i=1;i<=n;i++)
18     {
19         sort(a[i]+1,a[i]+1+n);
20         ans=max(ans,a[i][n-1]);
21     }
22     cout<<1<<endl;
23     cout<<ans;
24 }
复制代码

独木桥

碰面立马掉头的含义其实就是可以灵魂穿透,类似于将军饮马把同侧转化成了异侧直线的意思,换言之,这与他们相互穿过并没有任何区别。

对于每一个士兵,都有向左向右两种选择,设士兵在位置x,如果向左,需要x时间单位;向右,需要L-x+1个。分别取max和min,更新答案即可。

复制代码
 1 #include <bits/stdc++.h>
 2 using namespace std;
 3 int MAX,MIN;
 4 int main()
 5 {
 6     ios::sync_with_stdio(false),cin.tie(0),cout.tie(0);
 7     int l,n;
 8     cin>>l>>n;
 9     for(int i=1;i<=n;i++)
10     {
11         int x;//起始坐标
12         cin>>x;
13         MAX=max(MAX,max(x,l-x+1));
14         MIN=max(MIN,min(x,l-x+1));
15     }
16     cout<<MIN<<' '<<MAX;
17     
18 }
复制代码

排队接水

题目链接:P1223 排队接水 - 洛谷 | 计算机科学教育新生态 (luogu.com.cn)

 排序不等式,对于每一个人,都有一个接水时间,后面的人要想接水就必须等待前面这个人的时间,即第一个人让后面的n-1人共等待了(n-1)×第一个人打水时间。

比如,三个人,3 2 1 分别表示打水时间,所以对于每个人打水时间就是 0  3 (3+2),所以可以得出公式:T总=∑(n-i)*t[i]

所以越前面的人打水时间越少(前面的权重越小),打水总时间越少。注意,如果数据是1e5,就有可能爆int,所以干脆直接开long long 

复制代码
 1 #include <bits/stdc++.h>
 2 using namespace std;
 3 const int N=1010;
 4 typedef long long LL;
 5 struct fun
 6 {
 7     int num;
 8     int val;
 9 }t[1010];
10 bool cmp(fun a,fun b)
11 {
12     return a.val<b.val;
13 }
14 int main()
15 {
16     int n;
17     cin>>n;
18     for(int i=1;i<=n;i++)
19     {
20         cin>>t[i].val;
21         t[i].num=i;
22     }
23     double res=0;
24     sort(t+1,t+1+n,cmp);
25     for(int i=1;i<=n;i++)
26     {
27         cout<<t[i].num<<' ';
28         res+=t[i].val*(n-i);
29     }
30     cout<<endl;
31     cout<<fixed<<setprecision(2)<<res/n;
32     return 0;
33 }
复制代码

 [NOIP2004 提高组] 合并果子 / [USACO06NOV] Fence Repair G

题目链接:P1090 [NOIP2004 提高组] 合并果子 / [USACO06NOV] Fence Repair G - 洛谷 | 计算机科学教育新生态 (luogu.com.cn)

经典Huffman树问题(合并的图相当于一颗完全二叉树)

每次合并重量最小的两堆果子即可。

时间复杂度
使用小根堆维护所有果子,每次弹出堆顶的两堆果子,并将其合并,合并之后将两堆重量之和再次插入小根堆中。

每次操作会将果子的堆数减一,一共操作 n−1 次即可将所有果子合并成1堆。每次操作涉及到2次堆的删除操作和1次堆的插入操作,计算量是 O(logn)。因此总时间复杂度是 O(nlogn)。

复制代码
 1 #include <bits/stdc++.h>
 2 using namespace std;
 3 int main()
 4 {
 5     int n;
 6     cin>>n;
 7     priority_queue<int,vector<int>,greater<int> >q;
 8     while(n--)
 9     {
10         int x;
11         cin>>x;
12         q.push(x);
13     }
14     int res=0;
15     while(q.size()>1)
16     {
17         int a,b;
18         a=q.top(),q.pop();
19         b=q.top(),q.pop();
20         res+=a+b;
21         q.push(a+b);
22     }
23     cout<<res;
24 }
复制代码



本文作者:Zac-saodiseng

本文链接:https://www.cnblogs.com/Zac-saodiseng/p/16952891.html

版权声明:本作品采用知识共享署名-非商业性使用-禁止演绎 2.5 中国大陆许可协议进行许可。

posted @   Zac-saodiseng  阅读(37)  评论(0编辑  收藏  举报
点击右上角即可分享
微信分享提示
评论
收藏
关注
推荐
深色
回顶
收起