NOIP2017提高组模拟赛 9 (总结)##

第一题 星星

	天空中有N(1≤N≤400)颗星,每颗星有一个唯一的坐标(x,y),(1≤x,y ≤N)。请计算可以覆盖至少K(1≤K≤N)颗星的矩形的最小面积。矩形的边必须平行于X轴或Y轴,长度必须为正整数。星如果在矩形的边上,也认为它是属于矩形内的。

  思路:枚举矩形左上角的x,以及在x轴上的长度(矩形的长),然后单调的往下扫。

#include<cstdio>
#include<algorithm>
#include<cmath> #define imax(a,b) ((a>b)?(a):(b))
#define imin(a,b) ((a<b)?(a):(b)) typedef long long ll; using namespace std; int n,ne,ans;
int sum[410][410];
bool d[410][410]; int main()
{
freopen("a.in","r",stdin);
freopen("a.out","w",stdout);
scanf("%d%d",&n,&ne);
ans=n*n;
for(int i=1;i<=n;i++)
{
int a,b;
scanf("%d%d",&a,&b); d[a][b]=1;
}
for(int i=1;i<=n;i++)
{
sum[i][0]=0;
for(int j=1;j<=n;j++) sum[i][j]=sum[i][j-1]+(d[i][j]?1:0);
}
for(int ll=1;ll<=n;ll++)
{
for(int i=1;i<=n-ll+1;i++)
{
int fr=1,la=1,ss=sum[fr][i+ll-1]-sum[fr][i-1];
while(la<=n)
{
while(ss<ne)
{
la++; ss+=sum[la][i+ll-1]-sum[la][i-1];
if(la>n) break;
}
if(la>n) break;
ans=imin(ans,(la-fr+1)*ll);
ss-=sum[fr][i+ll-1]-sum[fr][i-1]; fr++;
}
}
}
printf("%d\n",ans);
return 0;
}

第二题 战争

	X国和Y国是死对头,X国有N个炮台, Y国有M个基地和K个发电站,炮台、基地、发电站所在的位置的坐标都是整数。Y国的每个发电站能对距离其L以内(包括L)的基地供电。X国的每个炮台都可以发射无限次,每次发射可以击毁一个基地或者一个发电站,消耗的能量为两者距离的平方,这里的距离是欧几里德距离。X国决定要摧毁Y国的所有基地,我们说Y国的某个基地被摧毁的条件是:基地本身被直接摧毁或者对其供电的所有发电站被击。
问X国摧毁Y国所有基地需要消耗的总能量最小是多少。
提示:点(X1,Y1)和点(X2,Y2)的欧几里德距离是:
dis = sqrt((X2-X1)*(X2-X1)+(Y2-Y1)*(Y2-Y1)).

  经典的网络流01模型,直接构图,跑一次dinic就行了。

  S向各个基地基地bi连边,代价为距离基地bi最近的炮台之间的距离。

  各个电厂向T连边,代价为距离电厂ci最近的炮台之间的距离。

  若电厂ci可以供电给基地dj,那么基地dj连向电厂ci,代价为∞。

  图的S到T的最小割即为answer。

#include<cstdio>
#include<algorithm>
#include<cstring>
#include<cmath> #define imax(a,b) ((a>b)?(a):(b))
#define imin(a,b) ((a<b)?(a):(b)) typedef long long ll; using namespace std; const int N=50;
const int M=15000;
const int oo=1e9;
struct data { int x,y; } ad[N+10],bd[N+10],cd[N+10];
int to[M],h[M],ne[M],val[M],tt,S,T;
int vis[M],lev[M],q[M];
int an,bn,cn,L,bfstime; void read(int n,data* A)
{
for(int i=1;i<=n;i++) scanf("%d",&A[i].x);
for(int i=1;i<=n;i++) scanf("%d",&A[i].y);
} void add(int a,int b,int c)
{
to[++tt]=b; ne[tt]=h[a]; val[tt]=c; h[a]=tt;
to[++tt]=a; ne[tt]=h[b]; val[tt]=0; h[b]=tt;
} int dis(data A,data B) { return ((A.x-B.x)*(A.x-B.x)+(A.y-B.y)*(A.y-B.y)); } void init()
{
scanf("%d%d%d%d",&an,&bn,&cn,&L);
read(an,ad); read(bn,bd); read(cn,cd);
tt=1; S=110; T=111;
for(int i=1;i<=bn;i++)
{
int dd=oo;
for(int j=1;j<=an;j++) dd=imin(dd,dis(ad[j],bd[i]));
add(S,i,dd);
}
for(int i=1;i<=cn;i++)
{
int dd=oo;
for(int j=1;j<=an;j++) dd=imin(dd,dis(ad[j],cd[i]));
add(50+i,T,dd);
}
int ml=L*L;
for(int i=1;i<=bn;i++)
{
for(int j=1;j<=cn;j++)
if(dis(bd[i],cd[j])<=ml) add(i,50+j,oo);
}
} bool bfs()
{
lev[S]=1; vis[S]=++bfstime;
int he=1,ta=1; q[1]=S;
while(he<=ta)
{
int u=q[he++];
for(int p=h[u];p;p=ne[p])
{
int v=to[p];
if(vis[v]==bfstime || !val[p]) continue;
q[++ta]=v; vis[v]=bfstime; lev[v]=lev[u]+1;
}
}
return (vis[T]==bfstime);
} int dfs(int now,int maxf)
{
int ret=0,t=0;
if(!maxf || now==T) return maxf;
for(int p=h[now];p;p=ne[p])
{
int v=to[p];
if(lev[v]!=lev[now]+1 || !val[p]) continue;
t=dfs(v,imin(maxf,val[p]));
ret+=t; maxf-=t;
val[p]-=t; val[p^1]+=t;
}
if(!maxf) lev[now]=-1;
return ret;
} int dinic()
{
int ret=0;
while(bfs()) ret+=dfs(S,oo);
return ret;
} int main()
{
freopen("b.in","r",stdin);
freopen("b.out","w",stdout);
init();
printf("%d\n",dinic());
return 0;
}

第三题 染色树

	一棵共含有X个结点的树,结点编号1至X,根结点编号是1。有Y种不同的颜色,颜色编号从1至Y。
现在给每个结点都染上一种颜色,整颗树染色后满足:
1、对于编号是i的颜色,整颗树当中,至少有一个结点被染成了颜色i。
2、根结点必须被染成1号颜色,而且整颗树当中,恰好要有Z个结点被染成1号颜色。 染色过程结束后,现在要计算染色的总代价,总代价等于每一条边的代价之和,那么怎么计算一条边的代价呢?
不妨设结点a与结点b之间有一条边,该边的权重是W。
1、如果结点a和结点b最终被染成不同的颜色,那么a与b之间的那条边的代价等于0。
2、如果结点a和结点b最终被染成相同的颜色,那么a与b之间的那条边的代价等于W。 现在的问题是:在满足上述要求的前提下,染色树最小的总代价是多少?如果无法完成染色的任务,输出-1。

  显然的,这是一道树形DP题(DP做的有点多-_-||),X,Y,Z好像都很大。直接做无疑是超时的。

  那么想考虑一下,answer=-1的情况。每个节点都可以是任意颜色(只是会有代价而已),唯一不满足的情况就是Z>X-Y+1(极限情况)。

  这是一棵树(这很重要),那么只需要两种颜色就可以使整棵树的任意x和x的父亲的颜色不同。

  又多了一个颜色1恰好为Z的限制条件,那么也只需要3种颜色就行了(多余的颜色是没任何作用的)。

  时间复杂度:O(9N³)

#include<cstdio>
#include<algorithm>
#include<cmath> #define imax(a,b) ((a>b)?(a):(b))
#define imin(a,b) ((a<b)?(a):(b)) typedef long long ll; using namespace std; const int oo=1e9;
const int M=700;
int X,Y,Z,ans;
int to[M],ne[M],h[M],val[M],tt;
int f[302][4][302]; void add(int a,int b,int c)
{
to[++tt]=b; ne[tt]=h[a]; h[a]=tt; val[tt]=c;
to[++tt]=a; ne[tt]=h[b]; h[b]=tt; val[tt]=c;
} void dfs(int x,int fa)
{
for(int i=1;i<=Y;i++)
{
for(int j=0;j<=Z;j++) f[x][i][j]=oo;
if(i==1) f[x][i][1]=0; else f[x][i][0]=0;
}
for(int p=h[x];p;p=ne[p])
{
int v=to[p];
if(v==fa) continue;
dfs(v,x);
for(int i=1;i<=Y;i++)
for(int j=Z;j>=0;j--)
{
int bes=oo;
for(int g=1;g<=Y;g++) bes=imin(bes,f[v][g][0]+(i==g?val[p]:0));
f[x][i][j]=imin(oo,f[x][i][j]+bes);
for(int k=1;k<=j;k++)
{
int yu=oo;
for(int g=1;g<=Y;g++) yu=imin(yu,f[v][g][k]+(i==g?val[p]:0));
f[x][i][j]=imin(f[x][i][j],f[x][i][j-k]+yu);
}
}
}
} int main()
{
freopen("c.in","r",stdin);
freopen("c.out","w",stdout);
scanf("%d%d%d",&X,&Y,&Z); tt=1;
if(Z>X-Y+1) printf("-1\n"); else
{
Y=imin(Y,3);
for(int i=1;i<X;i++) { int a,b,c; scanf("%d%d%d",&a,&b,&c); add(a,b,c); }
dfs(1,1);
printf("%d\n",f[1][1][Z]);
}
return 0;
}

  终于拿了一次AK了(虽然这次的题目有点水……)。

NOIP2017提高组模拟赛 9 (总结)的更多相关文章

  1. NOIP2017提高组 模拟赛15(总结)

    NOIP2017提高组 模拟赛15(总结) 第一题 讨厌整除的小明 [题目描述] 小明作为一个数学迷,总会出于数字的一些性质喜欢上某个数字,然而当他喜欢数字k的时候,却十分讨厌那些能够整除k而比k小的 ...

  2. NOIP2017提高组 模拟赛13(总结)

    NOIP2017提高组 模拟赛13(总结) 第一题 函数 [题目描述] [输入格式] 三个整数. 1≤t<10^9+7,2≤l≤r≤5*10^6 [输出格式] 一个整数. [输出样例] 2 2 ...

  3. NOIP2017提高组模拟赛 10 (总结)

    NOIP2017提高组模拟赛 10 (总结) 第一题 机密信息 FJ有个很奇怪的习惯,他把他所有的机密信息都存放在一个叫机密盘的磁盘分区里,然而这个机密盘中却没有一个文件,那他是怎么存放信息呢?聪明的 ...

  4. NOIP2017提高组模拟赛 8(总结)

    NOIP2017提高组模拟赛 8(总结) 第一题 路径 在二维坐标平面里有N个整数点,Bessie要访问这N个点.刚开始Bessie在点(0,0)处. 每一步,Bessie可以走到上.下.左.右四个点 ...

  5. NOIP2017提高组模拟赛 7(总结)

    NOIP2017提高组模拟赛 7(总结) 第一题 斯诺克 考虑这样一个斯诺克球台,它只有四个袋口,分别在四个角上(如下图所示).我们把所有桌子边界上的整数点作为击球点(除了4个袋口),在每个击球点我们 ...

  6. NOIP2017提高组模拟赛5 (总结)

    NOIP2017提高组模拟赛5 (总结) 第一题 最远 奶牛们想建立一个新的城市.它们想建立一条长度为N (1 <= N <= 1,000,000)的 主线大街,然后建立K条 (2 < ...

  7. NOIP2017提高组模拟赛4 (总结)

    NOIP2017提高组模拟赛4 (总结) 第一题 约数 设K是一个正整数,设X是K的约数,且X不等于1也不等于K. 加了X后,K的值就变大了,你可以重复上面的步骤.例如K= 4,我们可以用上面的规则产 ...

  8. 计蒜客NOIP2017提高组模拟赛(三)day1

    火山喷发 火山喷发对所有附近的生物具有毁灭性的影响.在本题中,我们希望用数值来模拟这一过程. 在环境里有 n 个生物分别具有 A​1​​,A​2​​,⋯,A​n​​点生命值,一次火山喷发总计 MM 轮 ...

  9. 计蒜客NOIP2017提高组模拟赛(四)day1

    T1:小X的质数 小 X 是一位热爱数学的男孩子,在茫茫的数字中,他对质数更有一种独特的情感.小 X 认为,质数是一切自然数起源的地方. 在小 X 的认知里,质数是除了本身和 1 以外,没有其他因数的 ...

随机推荐

  1. BZOJ 2435: [Noi2011]道路修建 dfs搜图

    2435: [Noi2011]道路修建 Description 在 W 星球上有 n 个国家.为了各自国家的经济发展,他们决定在各个国家之间建设双向道路使得国家之间连通.但是每个国家的国王都很吝啬,他 ...

  2. 创建多线程的HttpClient

    在实际的应用中,我们的联网应用程序里应该有一个HttpClient,并将其用于所有的HTTP通信.这就可能在同一个Http Client同时发出多个请求,也就产生了多线程的问题.幸运的是,在HttpC ...

  3. Android系统编译【转】

    本文转载自;http://blog.csdn.net/zirconsdu/article/details/8005415 Android编译系统分析 概要 由于android编译系统的复杂和使用了不熟 ...

  4. 【BZOJ 1878】 HH的项链

    [题目链接] https://www.lydsy.com/JudgeOnline/problem.php?id=1878 [算法] 显然,在线算法是不可做的,考虑离线算法 笔者的做法是莫队算法,时间复 ...

  5. Java IO 基础

    早上复习了IO.NIO.AIO相关的概念,将其中一些要点记录一下. 从编程语言层面 BIO | NIO | AIO 以Java的角度,理解,linux c里也有AIO的概念(库),这些概念不知道什么原 ...

  6. BZOJ 4241 分块

    思路: 考虑分块 f[i][j]表示从第i块开头到j的最大值 cnt[i][j]表示从第i块开始到序列末尾j出现了多少次 边角余料处理一下就好啦~ //By SiriusRen #include &l ...

  7. 了解和解决SQL SERVER阻塞问题(copy)

    http://support.microsoft.com/kb/224453 Summary In this article, the term "connection" refe ...

  8. HTML大纲

  9. TCP基本概念

    TCP协议是一个复杂的.可靠的字节流协议.不通用UDP协议. TCP提供客户与服务器之间的连接.TCP客户先与给定的服务器建立一个连接,再跨该连接与服务器交换数据,最后终止这个连接. TCP提供了可靠 ...

  10. 人人都是产品经理?关于PM你不知道的还有很多

    产品经理的职称最早出现在P&G宝洁公司,因效果非常显著,许多企业纷纷仿而效尤.硅谷知名的产品管理大师Marty Cagan在<Inspired: How To Create Produc ...