您的位置:首页 > Web前端 > React

CodeForces 607A Chain Reaction

2016-07-13 11:09 387 查看
题意是有一系列塔,每个塔位置不同攻击范围不同,塔只攻击右侧,范围内的(包括边界塔不包括本身);按从右到左的顺序点燃,被破坏掉的将不能点燃;要求:在最右侧再添一个塔并第一个点燃,使破坏掉的塔的数目最少
涉及递推,2ms时限,优化3次ac

!!不考虑新加的塔《给出一系列塔的位置和破坏范围,(ps:自己把它当成一个串觉的好理解)可求出这一系列(这个串)当点燃时破环的塔数》。

//在暴力枚举中发现可以递推
#include<cstdio>
#include<iostream>
using namespace std;
const int N=1000005; //一百万的值
const int Max=99999999;
int a
; //下标记录塔的位置对应值记录攻击范围
int b
;//记录从0到下标位置(下标位置被点燃后)(这个串)要破坏塔的数量
int book
;//记录对应下标位置是否有塔
int main(){
int n;
scanf("%d",&n);
for(int i=0;i<n;i++)
{
int x,y;
scanf("%d%d",&x,&y);
a[x]=y;
book[x]=1;    //book不可少 万一攻击范围为零
}
int num=0,maxn=Max,k=0;
for(int i=0;i<N;i++) //按从左到右的方向找塔
{
if(book[i]){     //枚举每个塔  这时已假设塔右方的所有塔已被新添加的塔破坏掉了
num++;
int sum=0;
for(int j=i-1;j>=i-a[i]&&j>=0;j--) //在这个塔攻击范围里有几个塔(这些塔将被摧毁)
{
if(book[j]) sum++;
}
for(int j=i-a[i]-1;j>=0;j--)
{
if(book[j]) {b[i]+=b[j];break;} //攻击范围外的第一个塔(前一个串的值)递推公式:b[i]=b[j]+sum;
}
b[i]+=sum;
if(b[i]+n-num<maxn) maxn=b[i]+n-num;  //求出的b[i]值加右侧被被破坏的塔得到完整的值
}
}
printf("%d\n",maxn);
return 0;
}
//以为if判断会很快结果超时
初次:
//优化,代码可以很简便但超时
//不再用一百万数组的下标记录塔而直接用十万的结构体储存
#include<iostream>
#include<algorithm>
#include<cstdio>
using namespace std;
const int N=100005;
const int Max=999999999;
struct f{
int x,y;
}a
;
int b
;
bool cmp(f p,f q){
return p.x<q.x;
}
int main(){
int n;
scanf("%d",&n);
for(int i=0;i<n;i++)
scanf("%d%d",&a[i].x,&a[i].y);
sort(a,a+n,cmp);
int maxn=Max;
for(int i=0;i<n;i++)
{
int j,sum=0;
for(j=i-1;j>=0;j--)
{
if(a[j].x>=a[i].x-a[i].y){sum++;}
else break;
}
if(j>=0) b[i]+=b[j]+sum;
if(b[i]+n-(i+1)<maxn) maxn=b[i]+n-(i+1);
}
printf("%d\n",maxn);
return 0;
}
AC:
//空间换时间添加2个一百万的数组,用两种方式记录数据
#include<iostream>
#include<algorithm>
#include<cstdio>
using namespace std;
const int N=100005;
const int M=1000005;
const int Max=999999999;
struct f{
int x,y;
}a
;   // 记录数据的数组(1)
int b
; //递推数组
int c[M]; // 第一个代码的记录方式(2)
int num[M]; //到下标位置塔的数量
bool cmp(f p,f q){
return p.x<q.x;
}
int main(){
int n;
scanf("%d",&n);
for(int i=1;i<=n;i++)
{
scanf("%d%d",&a[i].x,&a[i].y);
c[a[i].x]=a[i].y;
}
int s=0;
for(int i=0;i<M;i++) //预处理
{
if(c[i]){s++;}
num[i]=s;
}
sort(a+1,a+n+1,cmp);
int maxn=Max;
for(int i=1;i<=n;i++)  //一百万 到 十万
{
int p;
if(a[i].x-a[i].y-1>=0) p=num[a[i].x-1]-num[a[i].x-a[i].y-1]; //一百万 到 一 内层循环处理掉
else p=num[a[i].x-1];
b[i]+=p; //p相当于上个的sum
if(i-p-1>=0) b[i]+=b[i-p-1];//这个相当于上个的b[j]
if(b[i]+n-i<maxn) maxn=b[i]+n-i; //完整值
}
printf("%d\n",maxn);
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: