马上注册,结交更多好友,享用更多功能,让你轻松玩转社区。
您需要 登录 才可以下载或查看,没有账号?立即注册
×
简单贪心
1.P10452 货仓选址 - 洛谷
- #include<iostream>
- #include<algorithm>
- using namespace std;
- typedef long long LL;
- const int N = 1e5+10;
- LL a[N];
- LL n;
- int main()
- {
- cin>>n;
- for(int i = 1;i <= n;i++)cin>>a[i];
- sort(a+1,a+1+n);//排序
- LL sum = 0;
- //for(int i = 1;i <= n;i++)
- //{
- // sum+=(abs(a[i]-a[(1+n)/2]));
- //}
-
- for(int i = 1;i <= n/2;i++)
- {
- sum += abs(a[i]-a[n+1-i]);
- }
- cout<<sum<<endl;
- return 0;
- }
复制代码 2.P1115 最大子段和 - 洛谷
- #include<iostream>
- using namespace std;
- typedef long long LL;
- const int N = 2e5+10;
- LL a[N];
- LL n;
- int main()
- {
- cin>>n;
- for(int i = 1;i <= n;i++)cin>>a[i];
-
- LL sum = 0;LL ret = -1e5;
- for(int i = 1;i <= n;i++)
- {
- sum+=a[i];
- ret = max(sum,ret);
- if(sum < 0)sum = 0;
- }
- cout<<ret<<endl;
- return 0;
- }
复制代码 舍弃的想法很大胆,也很有风险,但通过证实,就可以表现通过
3. P1094 [NOIP 2007 遍及组] 怀念品分组 - 洛谷
- #include<iostream>
- #include<algorithm>
- using namespace std;
- int w,n;
- const int N = 3e4+10;
- int a[N];
- int main()
- {
- cin>>w>>n;
- for(int i = 1;i <= n;i++)cin>>a[i];
- //排序
- sort(a+1,a+1+n);
- int l = 1,r = n,ret = 0;
- while(l <= r)
- {
- //最小和最大相加小于w,符合 ,同时异位
- if(a[l]+a[r]<=w)l++,r--;
- //l待定。r--
- else
- {
- r--;
- }
- ret++;
- }
- cout<<ret<<endl;
- return 0;
-
- }
复制代码 4.P1056 [NOIP 2008 遍及组] 排座椅 - 洛谷
- #include<iostream>
- #include<algorithm>
- using namespace std;
- int m, n, k, l, d;
- const int N = 1010;
- struct node
- {
- int index;//存行列的下标
- int cnt;//存取该行或者该列能隔开多少对同学
- }row[N],col[N];
- //按照cnt从大到小排列
- bool cmp1(node& x, node& y)
- {
- return x.cnt > y.cnt;
- }
- //按照下标从小到大排列
- bool cmp2(node& x, node& y)
- {
- return x.index < y.index;
- }
- int main()
- {
- cin >> m >> n >> k >> l >> d;
- //初始化数组,赋值index
- for (int i = 1; i <= m; i++)row[i].index = i;
- for (int i = 1; i <= n; i++)col[i].index = i;
- //计算cnt
- while (d--)
- {
- int x, y, p, q; cin >> x >> y >> p >> q;
- if (x == p)col[min(y, q)].cnt++;
- else
- row[min(x, p)].cnt++;
- }
- //通过cnt把大的排在前面-->cmp1
- sort(row + 1, row + 1 + m, cmp1);
- sort(col + 1, col + 1 + n, cmp1);
- //把前k或者l大的按照下表从小到大进行排列
- sort(row + 1, row + 1 + k, cmp2);
- sort(col + 1, col + 1 + l, cmp2);
- //输出
- //行
- for (int i = 1; i <= k; i++)
- {
- cout << row[i].index << " ";
- }
- cout << endl;
- //列
- for (int i = 1; i <= l; i++)
- {
- cout << col[i].index << " ";
- }
- return 0;
- }
复制代码 1.把每一行和每一列可以隔开的同砚纪录到cnt中
2.按照cnt从大到小举行分列
3.按照index对前k大概l个举行从小到大的分列
4.输出前k 或 l的index下标
4.矩阵消除游戏
- #include<iostream>
- #include<algorithm>
- #include<cstring>
- using namespace std;
- int calc(int x)
- {
- int ret = 0;
- while (x)
- {
- x = x & (x - 1);
- ret++;
- }
- return ret;
- }
- bool cmp(int x, int y)
- {
- return x > y;
- }
- int n, m,k;
- const int N = 100;
- int a[N][N];
- int col[N];
- int main()
- {
- cin >> n >> m >> k;
- for (int i = 0; i < n; i++)
- {
- for (int j = 0; j < m; j++)
- {
- cin >> a[i][j];
- }
- }
- int sum = 0, ret = 0;
- //暴力枚举所有的第一行
- for (int st = 0; st < (1 << n); st++)
- {
- sum = 0;
- int num_1 = calc(st);
- //超过就不要了
- if (num_1 > k)continue;
- memset(col, 0, sizeof(col));
- for (int i = 0; i < n; i++)
- {
- //加上当前行的数字
- for (int j = 0; j < m; j++)
- {
- if (((st >> i) & 1) == 1)
- {
- sum += a[i][j];
- }
- else
- {
- col[j] += a[i][j];
- }
- }
- }
- //对列进行从大到小排序,取前k - num_1个
- int remain = k - num_1;
- sort(col, col + m, cmp);
- for (int i = 0; i < remain; i++)sum += col[i];
- ret = max(ret, sum);
- }
- cout << ret << endl;
- return 0;
- }
复制代码 暴力摆列行的全部选择方法,然后设置col,纪录行选择后,列的数据,remain表现剩余的操纵次数,对摆列行排序,取最大的前remain个即可。,
推公式
1.在确定好的序次序列中,拿出相邻的两个元素
2.互换这两个元素,对前面和反面确定好序次的序列的结果不造成影响
3.根据这两个原色互换前后的结果推导出排序的规
1.P1012 [NOIP 1998 进步组] 拼数 - 洛谷
- #include<iostream>
- #include<algorithm>
- using namespace std;
- int n;
- const int N = 25;
- string st[N];
- bool cmp(string& x, string& y)
- {
- return x + y > y + x;
- }
- int main()
- {
- cin >> n;
- for (int i = 0; i < n; i++)
- cin >> st[i];
- sort(st, st+n, cmp);
- for (int i = 0; i < n; i++)
- cout << st[i];
- return 0;
- }
复制代码 比力方法:两两元素相拼,
2.P2878 [USACO07JAN] Protecting the Flowers S - 洛谷
很震惊!!
1.在确定好的序次序列中,拿出相邻的两个元素
2.互换这两个元素,对前面和反面确定好序次的序列的结果不造成影响
3.根据这两个原色互换前后的结果推导出排序的
- #include<iostream>
- #include<algorithm>
- using namespace std;
- typedef long long LL;
- LL n;
- const int N = 1e5+10;
- struct node
- {
- LL t;//时间
- LL d;//吃草速度
- }a[N];
- bool cmp(node& x,node&y)
- {
- return x.t*y.d < x.d*y.t;
- }
- int main()
- {
- cin>>n;
- for(int i = 1;i <= n;i++)
- {
- cin>>a[i].t>>a[i].d;
- }
- sort(a+1,a+n+1,cmp);
- LL ret = 0,t = 0;
- for(int i = 1;i <= n;i++)
- {
- ret += a[i].d*t;
- t += 2*a[i].t;
- }
- cout<<ret<<endl;
- }
复制代码 3. P1842 [USACO05NOV] 奶牛玩杂技 - 洛谷
- #include<iostream>
- #include<algorithm>
- using namespace std;
- typedef long long LL;
- const int N = 5e4+10;
- int n;
- struct node
- {
- LL w;
- LL s;
- }a[N];
- //推公式得到,把max中较小的放在前面,会让总体压力值变得较小
- bool cmp(node&x,node&y)
- {
- return max(-x.s,x.w-y.s) < max(-y.s,y.w-x.s);
- }
- int main()
- {
- cin>>n;
- for(int i = 1;i <= n;i++)
- {
- cin>>a[i].w>>a[i].s;
- }
- sort(a+1,a+1+n,cmp);
-
- LL w = 0;
- LL ret = -1e5;
- for(int i = 1;i <= n;i++)
- {
- ret = max(ret,w - a[i].s);
- w+=a[i].w;
- }
- cout<<ret<<endl;
- return 0;
-
- }
复制代码
哈夫曼树
1.P1090 [NOIP 2004 进步组] 归并果子 - 洛谷
- #include<iostream>
- #include<queue>
- #include<vector>
- using namespace std;
- typedef long long LL;
- priority_queue<LL,vector<LL>,greater<LL>>heap;
- LL n;
- int main()
- {
- cin>>n;
- for(int i = 1;i <= n;i++)
- {
- LL x;cin>>x;
- heap.push(x);
- }
- LL sum = 0;
- while(heap.size()>1)
- {
- LL x = heap.top();heap.pop();
- LL y = heap.top();heap.pop();
- sum+=(x+y);
- heap.push(x+y);
- }
- cout<<sum<<endl;
- }
复制代码 区间标题
这种题⽬的办理⽅式⼀般就是按照区间的左端点大概是右端点排序,然后在排序之后的区间上,根据 题⽬要求,订定出相应的贪⼼计谋,进⽽得到最优解。
具体是根据左端点还是右端点排序?升序还是降序?⼀般是假设⼀种排序⽅式,而且订定贪⼼计谋, 当没有显着的反例时,就可以实验去写代码。
1.P1803 缭乱的yyy / 线段覆盖 - 洛谷
- #include<iostream>
- #include<algorithm>
- using namespace std;
- const int N = 1e6+10;
- int n;
- struct node
- {
- int s;
- int e;
- }a[N];
- bool cmp(node&x,node&y)
- {
- return x.s < y.s;
- }
- int main()
- {
- cin>>n;
- for(int i = 1;i <= n;i++)
- {
- cin>>a[i].s;
- cin>>a[i].e;
- }
-
- sort(a+1,a+1+n,cmp);//按照起点开始由小到大的顺序排列
- int ret = 1;
- int r = a[1].e;
- for(int i = 2;i <= n;i++)
- {
- int right = a[i].e,left = a[i].s;
- if(left < r)//重叠了,不能参加,如果重叠的右端比前面那一个还小,那就贪,覆盖前面哪一个
- {
- r = min(r,right);
- }
- else
- {
- ret++;//没有重叠,可以参加
- r = right;//更新较小的r
- }
- }
- cout<<ret<<endl;
- return 0;
-
- }
复制代码
2.UVA1193 Radar Installation - 洛谷
按照左端点排序,相互重叠的区间是连续的
二维标题转化成一维标题
证实: 按照左端点排序,相互重叠的区间是连续的
- #include<iostream>
- #include<cmath>
- #include<algorithm>
- using namespace std;
- const int N = 1e3+10;
- int n,d;
- struct node
- {
- double l;
- double r;
- }a[N];
- bool cmp(node&x,node&y)
- {
- return x.l < y.l;
- }
- int main()
- {
- int cnt = 1;
- while(cin>>n>>d&&(n&&d))
- {
- int flag = 1;
- for(int i = 1;i <= n;i++)
- {
- int x,y;cin>>x>>y;
- if(y > d)flag = -1;
- //把二维映射到一维上去
- double l = sqrt(d*d - y*y);
- a[i].l = x - l;
- a[i].r = x + l;
- }
- sort(a+1,a+1+n,cmp);
- int ret = 1;
- int r = a[1].r;
- cout<<"Case "<<cnt<<": ";
- cnt++;
- for(int i = 2;i <= n;i++)
- {
- int left = a[i].l,right = a[i].r;
- if(left<=r)//等于也可以扫到
- {
- //扫描通过
- r = min(r,right);
- }else
- {
- ret++;
- r = right;
- }
- }
-
- cout<<ret<<endl;
- }
- return 0;
- }
复制代码
3.P2887 [USACO07NOV] Sunscreen G - 洛谷
- #include<iostream>
- #include<algorithm>
- using namespace std;
- const int N = 3e3+10;
- int n,l;
- struct node
- {
- int l;//表示奶牛耐受的最小值//防晒霜的防晒值
- int r;//奶牛耐受的最大值// 防晒霜的数量
- }a[N],b[N];
- bool cmp(node&x,node&y)
- {
- return x.l > y.l;
- }
- int main()
- {
- cin>>n>>l;
- for(int i = 1;i <= n;i++)
- {
- cin>>a[i].l>>a[i].r;//输入奶牛耐受值
- }
- for(int i = 1;i <= l;i++)
- {
- cin>>b[i].l>>b[i].r;//输入防晒霜的防晒值和数量
- }
- //按照奶牛奶牛左端从大到小进行排序
- sort(a+1,a+1+n,cmp);
- //按照防晒霜防晒值从大到小进行排序
- sort(b+1,b+1+l,cmp);
- int ret = 0;
- for(int i = 1;i <= n;i++)
- {
- //选择一种防晒霜
- for(int j = 1;j <= l;j++)
- {
- if(b[j].r == 0)continue;
- if(b[j].l<=a[i].r&&b[j].l>=a[i].l)
- {
- //符合条件,ret++,数量--
- ret++;
- b[j].r--;
- break;//选完一个就直接除去,免得后面的都没了
- }
- }
- }
- cout<<ret<<endl;
- return 0;
- }
复制代码
4.P2859 [USACO06FEB] Stall Reservations S - 洛谷

- #include<iostream>
- #include<queue>
- #include<algorithm>
- using namespace std;
- const int N = 5e4 + 10;
- int n;
- struct node
- {
- int l;//牛牛的开始//该牛棚的结束时间
- int r;//牛牛的结束 //该牛棚的编号
- int num;//这只牛的编号
- bool operator<(const node& y)const
- {
- return l > y.l;//创建小根堆
- }
- }a[N];
- bool cmp(node& x, node& y)
- {
- return x.l < y.l;
- }
- int res[N];//记录每只牛进入的牛棚顺序
- priority_queue<node> heap;//建议一个关于牛棚结束时间的小根堆,找出当前技术时间最早的,拉出来
- int main()
- {
- cin >> n;
- for (int i = 1; i <= n; i++)
- {
- cin >> a[i].l >> a[i].r;
- a[i].num = i;
- }
- //按照左端点从小到大排列
- sort(a + 1, a + 1 + n, cmp);
- int ret = 1;//记录牛棚状态
- heap.push({ a[1].r,1 });
- res[a[1].num] = 1; //一号牛进一号棚
- for (int i = 2; i <= n; i++)
- {
- int l = a[i].l, r = a[i].r;
- int ete = heap.top().l;
- int num_peng = heap.top().r;
- if (ete >= l)//如果最短结束时间都>这只牛的开始的起始时间,那么就必须新开一个牛棚
- {
- ret++;
- heap.push({ r,ret });
- res[a[i].num] = ret;
- }
- else//可以拿下
- {
- heap.pop();//结束不要了
- heap.push({ r,num_peng });//把这只牛推入彭中
- res[a[i].num] = num_peng;
- }
- }
- cout << ret << endl;
- for (int i = 1; i <= n; i++)cout << res[i] << endl;
- }
复制代码
|