SSL Week 6 总结&解题报告

总结

日期事件刷的题
Day 0(星期天)做题NOIP2017普及组解题报告
Day 1(星期一)写博客
Day 2(星期二)做题新二叉树FBI树数字三角形吃奶酪合唱队形导弹拦截
Day 3(星期三)讲课一直在改题
Day 4(星期四)做题AsteroidsKnights
Day 5(星期五)刷题最小路径覆盖增广路导弹拦截第二问Chessboard
Day 6(星期六)模拟赛模拟赛的题,place the robots最大正方形吃吃吃

时间复杂度

题目时间复杂度
第一题 数列 O(logd(n)) O ( l o g d ( n ) )
第二题 蚂蚁 O(4000n2) O ( 4000 n 2 )
第三题 单元格 O(n2) O ( n 2 )
第四题 剪草 O(n3) O ( n 3 )

解题报告

题目

第一张
第二张
第三张
第四张

第一题 数列

思路

对于等差数列,直接暴力规律求解,对于等比数列,直接暴力模拟

代码

#include<iostream>
#include<cstdio>
#define ULL unsigned long long
using namespace std;ULL a,b,c,d,n,ans;
int main()
{
    cin>>a>>b>>c>>d>>n;//输入
    if(n>a)ans=(n-a)/b+1;//计算
    while(c<=n)
    {
        if(c<a||(c-a)%b) ans++;//判断在不在
        c*=d;
        if(d==1)break;//特判
    }
    cout<<ans;//输出
}

第二题 蚂蚁

思路

暴力模拟,模拟每只蚂蚁慢慢爬

代码

#include<cstdio>
using namespace std;int n,x,y,ans;char s[51];bool ok;
struct node
{
    char w;
    double x,y;
}a[51];
double t=2005;//一直爬
bool check(int x)//判断此蚂蚁是否消失
{
    return a[x].w=='S'||a[x].w=='N'||a[x].w=='E'||a[x].w=='W';
}
int main()
{
    scanf("%d\n",&n);
    gets(s+1);
    for(int i=1;i<=n;i++)
     {scanf("%lf%lf",&a[i].x,&a[i].y);a[i].w=s[i];}//输入+初始化
    while(t-=0.5)//继续爬
    {
        for(int i=1;i<=n;i++)
        {
            if(a[i].w=='N') a[i].y+=0.5;else
            if(a[i].w=='S') a[i].y-=0.5;else
            if(a[i].w=='E') a[i].x+=0.5;else
            if(a[i].w=='W') a[i].x-=0.5;//爬
        }
        for(int i=1;i<n;i++)
        {
            ok=false;
            for(int j=i+1;j<=n;j++)
             if(a[i].x==a[j].x&&a[i].y==a[j].y&&check(i)&&check(j))//看看有没有蚂蚁会消失
              {a[j].w='\0';ok=true;}//标记已经消失
            if(ok)a[i].w='\0';//若有蚂蚁消失,此蚂蚁也消失
        }
    }
    for(int i=1;i<=n;i++) ans+=check(i);//判断
    printf("%d",ans);//输出
}

第三题 单元格

思路

找规律

代码

#include<cstdio>
using namespace std;long long n,m;int x,y;long long ans;
int main()
{
    scanf("%lld%lld%d%d",&n,&m,&x,&y);//输入
    for(int i=3;i<=n;i++)
    {
        for(int j=3;j<=m;j++)
         if(((i+j-2)<<1)>=x&&((i+j-2)<<1)<=y)//是否在范围之内
          ans+=6*(i-2)*(j-2)*(n-i+1)*(m-j+1);//计算
        ans%=1000000007;//记得%
    }
    printf("%lld",ans);
}

第四题 剪草

思路

显然这题不能用贪心去做,因为如果每次割最长的,那么长得最快的那个又长起来了。如果割掉长得最快的,当你去割别的草的时候,这课草又长起来了。而且每棵草没有必要割两次。
所以想到了动态规划,设 F[j][k] F [ j ] [ k ] 表示前 j j 棵草,割了k次的时候所有草的总长度,显然可以得到动态转移方程

F[j][k]=min(f[j1][k]+a[j]+b[j]i,f[j1][k1]+(ik)b[j]) F [ j ] [ k ] = m i n ( f [ j − 1 ] [ k ] + a [ j ] + b [ j ] ∗ i , f [ j − 1 ] [ k − 1 ] + ( i − k ) ∗ b [ j ] )
(i为时间)

代码

#include<cstdio>
#include<algorithm>
#define r(i,a,b) for(int i=a;i<=b;i++)
#define file(x) freopen(#x".in","r",stdin);freopen(#x".out","w",stdout)
using namespace std;int n,m,f[56][56];
struct node{int a,b;}c[56];
bool cmp(node x,node y){return x.b<y.b;}
int main()
{
    file(grass);
    scanf("%d%d",&n,&m);
    r(i,1,n) scanf("%d",&c[i].a);
    r(i,1,n) scanf("%d",&c[i].b);
    stable_sort(c+1,c+1+n,cmp);//按生长速度排序
    r(i,0,n)//最多割n次
    {
     r(j,1,n)
      {
        f[j][0]=f[j-1][0]+c[j].a+c[j].b*i;//初始化
        r(k,1,i) f[j][k]=50234567;
      }
     r(j,1,n)
      r(k,1,i)
       f[j][k]=min(f[j-1][k]+c[j].a+c[j].b*i,f[j-1][k-1]+c[j].b*(i-k));//动态转移
     if(f[n][i]<=m) return printf("%d",i)&0;//满足条件就输出
    }
    puts("-1");//否则
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值