NOIP2017赛前模拟(4):总结
题目:
1.打牌
给定n个整数(n<=1000000),按照扑克牌对子(x,x)或者顺子(x,x+1,x+2)打出牌···问最多可以打出多少次对子或者顺子?牌的大小<=1000000
2.弹球
给定一个n*m的格子(n,m<=1000000000),已知一个球从(1,1)处出发向左下方滚出··每次遇到边界则旋转90度反弹(类似与镜面反射)直到滚到一个角落停止···途中球每次经过一个方格则会将方格染色(包括第一个方格),问只被染一次色的方格有多少个?
3.方盒子
已知有n个盒子(n<=200),每个盒子有长宽···一个盒子可以放入一个长和宽都不小于它的盒子(可以不断嵌套),一个盒子里只能套一层盒子例如1*2的盒子只能套一个1*1的盒子··而不能套两个··只能一个1*1的盒子套在另一个1*1的盒子里,套完后盒子的占地面积是套再最外面的盒子的面积之和··问最小占地面积是多少?
题解:
1.贪心
额··考试的时候脑子抽了··贪心贪错了··正解其实很简单··
如果某数字的牌小于2张直接出对子或者不出···如果大于3张的话我们可以考虑一直打对子直到只剩下一张或者两张··然后判断是否可以和之前两张牌打成顺子就可以了··因为对于打顺子这一次和打对子对答案的贡献是一样的··但打顺子的话我们会剩一张牌··这一张牌可能与后面的牌组成顺子从而对答案有多余贡献····
代码:
#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<cmath>
#include<ctime>
#include<cctype>
#include<string>
#include<cstring>
#include<algorithm>
using namespace std;
const int N=1e6+;
inline int R()
{
char c;int f=;
for(c=getchar();c<''||c>'';c=getchar());
for(;c<=''&&c>='';c=getchar()) f=(f<<)+(f<<)+c-'';
return f;
}
int n,maxx=,card[N];
int main()
{
//freopen("a.in","r",stdin);
n=R();int a;int ans=;
for(int i=;i<=n;i++) a=R(),card[a]++,maxx=max(maxx,a);
for(int i=;i<=maxx;i++)
{
if((card[i]&)&&(card[i+]&)&&(card[i+])) card[i]--,card[i+]--,card[i+]--,ans++;
ans+=card[i]/;
}
cout<<ans<<endl;
return ;
}
2.找规律
考试的时候看到这道题直接怂了····下来想想其实如果认真分析还是有可能做对的···哎····
具体过程由于我语文差实在用语言描述不出来··这里偷偷懒不写了··
代码:
#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<cmath>
#include<ctime>
#include<cctype>
#include<string>
#include<cstring>
#include<algorithm>
using namespace std;
inline long long R()
{
char c;long long f=;
for(c=getchar();c<''||c>'';c=getchar());
for(;c<=''&&c>='';c=getchar()) f=f*+c-'';
return f;
}
inline long long get(long long a,long long b)
{
if(b==) return a;
else return get(b,a%b);
}
int main()
{
//freopen("a.in","r",stdin);
int T;
long long a,b;
T=R();
while(T--)
{
a=R(),b=R();if(a<b) swap(a,b);
long long t=get(a-,b-);
long long s=(a-)*(b-)/t;
long long up=s/(b-);long long side=s/(a-);
cout<<s-(up-)*(side-)+<<endl;
}
return ;
}
3.二分图匹配+贪心/最大费用流
这道题还是比较容易想到的··
第一种方法是二分图匹配··左边的点向右边能够覆盖它的盒子连边···然后如果左边的盒子被匹配到了说明它被一个盒子覆盖了··因此想到我们要首先覆盖那些面积大的盒子··
所以在跑匈牙利算法时优先匹配那些面积大的盒子即可··
第二种方法其实和第一种本质是一样的··只是实现方式不同··和二分图一样每个盒子拆成左右两部分··建边方式和第一种一样··流量为1费用为左边盒子的面积··然后s向左边的点连流量为1费用为0的边··t向右边的点连流量飞1费用为0的边然后跑一边最大费用··用所有盒子的总面积减去最大费用(其实就是被覆盖的盒子的面积)就是答案
代码1:
#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<cmath>
#include<ctime>
#include<cctype>
#include<cstring>
#include<string>
#include<algorithm>
using namespace std;
const int N=;
struct node
{
int x,y;
}bx[N];
inline int R()
{
char c;int f=;
for(c=getchar();c<''||c>'';c=getchar());
for(;c<=''&&c>='';c=getchar()) f=(f<<)+(f<<)+c-'';
return f;
}
int n,ed[N][N],ans,belon[N];
bool visit[N];
bool cmp(node a,node b)
{
return a.x*a.y<b.x*b.y;
}
inline bool get(int x)
{
for(int i=n;i>x;i--)
if(ed[x][i]&&!visit[i])
{
visit[i]=true;
if(belon[i]==||get(belon[i]))
{
belon[i]=x;return true;
}
}
return false;
}
int main()
{
//freopen("box.in","r",stdin);
//freopen("box.out","w",stdout);
n=R();
for(int i=;i<=n;i++) bx[i].x=R(),bx[i].y=R();
sort(bx+,bx+n+,cmp);
for(int i=;i<=n;i++)
{
ans+=bx[i].x*bx[i].y;
for(int j=i+;j<=n;j++)
if(bx[j].x>=bx[i].x&&bx[j].y>=bx[i].y) ed[i][j]=true;
}
for(int i=n-;i>=;i--)
{
memset(visit,false,sizeof(visit));
if(get(i)) ans-=bx[i].x*bx[i].y;
}
cout<<ans<<endl;
return ;
}
代码2:注意memset时附上的值不能为负数
#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<cmath>
#include<ctime>
#include<cctype>
#include<string>
#include<cstring>
#include<algorithm>
#include<queue>
using namespace std;
queue<int>que;
const int N=;
const int inf=0x3f3f3f3f;
int first[N],next[N],go[N],cost[N],rest[N],tot=;
int dis[N];
bool visit[N],work[N];
struct node
{
int x,y;
inline friend bool operator == (node a,node b)
{
return a.x==b.x&&a.y==b.y;
}
}bx[N];
inline int R()
{
char c;int f=;
for(c=getchar();c<''||c>'';c=getchar());
for(;c<=''&&c>='';c=getchar()) f=(f<<)+(f<<)+c-'';
return f;
}
int n,src,des,ans;
inline void comb(int a,int b,int v,int w)
{
next[++tot]=first[a],first[a]=tot,go[tot]=b,rest[tot]=v,cost[tot]=w;
next[++tot]=first[b],first[b]=tot,go[tot]=a,rest[tot]=,cost[tot]=-w;
}
inline bool cmp(node a,node b)
{
if(a.x*a.y==b.x*b.y) return a.x<b.x;
else return a.x*a.y<b.x*b.y;
}
inline bool SPFA()
{
for(int i=;i<=des;i++)dis[i]=-inf;
memset(work,false,sizeof(work));
while(!que.empty())que.pop();
que.push(src),dis[src]=;
int u,v,e;
while(!que.empty())
{
u=que.front(),que.pop();
visit[u]=false;
for(e=first[u];e;e=next[e])
{
if(rest[e]>&&dis[u]+cost[e]>dis[v=go[e]])
{
dis[v]=dis[u]+cost[e];
if(!visit[v])
{
visit[v]=true;
que.push(v);
}
}
}
}
return dis[des]!=-inf;
}
inline int dinic(int u,int flow)
{
if(u==des)
{
ans+=flow*dis[des];
return flow;
}
work[u]=true;
int v,e,res=,delta;
for(e=first[u];e;e=next[e])
{
if(!work[v=go[e]]&&rest[e]>&&dis[u]+cost[e]==dis[v])
{
delta=dinic(v,min(rest[e],flow-res));
if(delta)
{
rest[e]-=delta,rest[e^]+=delta;
res+=delta;if(res==flow) break;
}
}
}
return res;
}
inline void getmax()
{
while(SPFA())
dinic(src,1e+);
}
int main()
{
//freopen("a.in","r",stdin);
n=R();src=,des=*n+;int sum=;
for(int i=;i<=n;i++) bx[i].x=R(),bx[i].y=R();
sort(bx+,bx+n+,cmp);
n=unique(bx+,bx+n+)-bx-;
for(int i=;i<=n;i++)
{
sum+=bx[i].x*bx[i].y;
for(int j=i+;j<=n;j++)
if(bx[j].x>=bx[i].x&&bx[j].y>=bx[i].y) comb(j,i+n,,bx[i].x*bx[i].y);
}
for(int i=;i<=n;i++) comb(src,i,,);
for(int i=;i<=n;i++) comb(i+n,des,,);
getmax();
cout<<sum-ans<<endl;
return ;
}
NOIP2017赛前模拟(4):总结的更多相关文章
- NOIP2017赛前模拟(3):总结
题目: 1.购买板凳(100) 大意:区间修改最后查询全局最大值; 2.新排序(40分暴力) 大意:给一串长度小于100000的数列···每次操作找出序列中严格小于其左边的数字或者严格大于其右边的数字 ...
- NOIP2017赛前模拟11月6日—7日总结
收获颇丰的两天··· 题目1:序列操作 给定n个非负整数,进行m次操作,每次操作给出c,要求找出c个正整数数并将它们减去1,问最多能进行多少操作?n,m<=1000000 首先暴力贪心肯定是每次 ...
- NOIP2017赛前模拟11月4日总结:
第一次挂0·····有点感伤···主要是因为时间分配太不合理了··花2个半小时搞第一题最后还wa完了··第二题很简单花了30分钟打完但没打对拍结果wa完···第三题暴力可以拿20分的但没时间打了··· ...
- NOIP2017赛前模拟11月2日总结
分数爆炸的一天··但也学了很多 题目1:活动安排 给定n个活动的开始时间与结束时间··只有一个场地··要求保留尽量多的活动且时间不冲突···场地数n<=100000 考点:贪心 直接将结束时间按 ...
- NOIP2017赛前模拟10月30日总结
题目1: n个人参赛(n<=100000),每个人有一个权值··已知两个人权值绝对值之差小于等于K时,两个人都有可能赢,若大于则权值大的人赢···比赛为淘汰制,进行n-1轮·问最后可能赢的人有多 ...
- NOIP2017赛前模拟(5):总结
题目: 1.刮刮卡 已知n(n<=1000000)张刮刮卡按顺序排列,刮开可以获得B元现金和B个积分,购买刮刮卡需要A元,某人若按照顺序刮开的话··当B的总和小于A时便会停止刮卡(即花出去的钱多 ...
- NOIP2017赛前模拟1:总结
题目: 1.造盒子 题目描述 企鹅豆豆收到了面积为 K 的一块橡皮泥.但是他没有合适的盒子来装下这个橡皮泥.所以他打算造一个盒子. 制造台是有方形网格的平台,每个小正方形边长为 1 .现在豆豆有两类木 ...
- NOIP2017年11月9日赛前模拟
最后一次NOIP模拟了····· 题目1:回文数字 Tom 最近在研究回文数字. 假设 s[i] 是长度为 i 的回文数个数(不含前导0),则对于给定的正整数 n 有:
- [NOIP2017]时间复杂度(模拟)
sscanf读入数字,getline(cin,string)读一整行,其余暴力模拟即可. #include<cstdio> #include<string> #include& ...
随机推荐
- UVA 1609 Foul Play 不公平竞赛 (构(luan)造(gao)+递归)
题意:有n支队伍(n是2的整数幂,2<=n<=4),打淘汰赛,胜者进入下一轮,其中1号队伍能打败至少一半的队伍,对于它不能打败的队伍l,一定存在一支它能够打败的队伍w,使得w能直接打败l, ...
- java 自定义容器,实现foreach
import java.util.Arrays; import java.util.Iterator; public class ArrayList implements Iterable<In ...
- JavaScript -- 操作符和逻辑运算
算数操作符 + : 加 - : 减 * : 乘 / : 除 %:取余 递增和递减 1.递增 ++a与a++都是对a进行递增的操作 区别 ++a先返回递增之后的a的值 a++先返回a的原值,再返回递增之 ...
- Java基础 匿名内部类 异常 多线程 集合面试题
匿名内部类:没有名字的内部类.就是内部类的简化形式.一般只用一次就可以用这种形式.匿名内部类其实就是一个匿名子类对象.想要定义匿名内部类:需要前提,内部类必须继承一个类或者实现接口. 匿名内部类的格式 ...
- spring IOC注解与xml配置
转载自:https://blog.csdn.net/u014292162/article/details/52277756 IOC 1小案例 将对象的依赖交给配置文件来配置(配置文件的名字是可以任意的 ...
- NodeJS基础入门-Buffer
Buffer.byteLength console.log(Buffer.byteLength('test')); console.log(Buffer.byteLength('我是C语言爱好者')) ...
- 蓝牙stack bluez学习(1)Stack Architecture
Bluez支持的features Core Specification 4.2 (GAP, L2CAP, RFCOMM, SDP, GATT) Classic Bluetooth (BR/EDR) B ...
- Qt概念和快捷键
Qt概念和快捷键 Qt简介 1.Qt的由来和发展 Qt是一个1991年由Qt Company开发的跨平台C++图形用户界面应用程序开发框架.它既可以开发GUI程序,也可用于开发非GUI程 ...
- 【windows】共享文件夹设置
控制面板\网络和 Internet\网络和共享中心\高级共享设置 在当前的域\公用\家庭网络 下文件和打印机共享开关打开 现在可以在 计算机-网络 里面看到共享的计算机啦 选中自己想要分享的文件,右键 ...
- Java-framework-Vaadin
安装vaadin: (1) 首先试了maven+vaadin. 安装maven: 1. unzip apache-maven-3.3.9-bin.zip 2. modify PATH environm ...