SSL Week 3 总结&解题报告

总结

日期 事件 刷的题
Day 0 星期日 做文档,写作业,刷比赛 购物券(dfs+hash)
Day 1 星期一 完善了博客
Day 2 星期二 讲课 NOI元旦
Day 3 星期三 做题 格子游戏
Day 4 星期四 刷题,写博客 矩形,搭配购买,旅行,嫌疑犯,宗教,雀斑
Day 5 星期五 出题
Day 6 星期六 模拟赛 模拟赛的题

时间复杂度

题目 时间复杂度
第一题 奇数 O(tofrom2) O ( t o − f r o m 2 )
第二题 求和 O(n+nn) O ( n + n n )
第三题 圆环 O(n+i=11..nlog(ai)) O ( n + ∑ 1.. n i = 1 l o g ( a i ) )
第四题 翻转 O(4n2) O ( 4 n 2 )
第五题 得分 O(nlogn+nm) O ( n l o g n + n m )
第六题 重要人物 O(n2+2G+KE) O ( n 2 + 2 G + K E )

解题报告

废话不多说,直接放题目
SSL Week 3 总结&解题报告_第1张图片
SSL Week 3 总结&解题报告_第2张图片
SSL Week 3 总结&解题报告_第3张图片
SSL Week 3 总结&解题报告_第4张图片
SSL Week 3 总结&解题报告_第5张图片
SSL Week 3 总结&解题报告_第6张图片
SSL Week 3 总结&解题报告_第7张图片
SSL Week 3 总结&解题报告_第8张图片

第一题 奇数

思路

最水的题,直接暴力。顺便练习下骚库(STL)

代码

#include
#include
using namespace std;int from,to;
vector<int>odd;
int main()
{
    scanf("%d%d",&from,&to);//输入
    if(!(from&1)) from++;if(!(to&1)) to--;//一些小优化
    for(int i=from;i<=to;i+=2) odd.push_back(i);//放入
    printf("%d\n",odd.size());//输出数量
    for(int i=0;iprintf("%d\n",odd[i]);//输出
}

第二题 求和

思路

直接模拟

代码

#include
#define r(i,a,b) for(int i=a;i<=b;i++)
using namespace std;int s,n=1,k,ans[101],p;
bool h[100001];
bool check(int x)//暴力判断
{
    if(!x) return true;//正好相等
    if(x&1) return false;//不是偶数
    x>>=1;//变成一半
    if(h[x]) //是否存在
    {
        ans[++p]=x;
        return true;//存在输出
    }
    r(i,1,n-1)
     r(j,i+1,n)
      if(i+j==x)//存在
       {
        ans[++p]=i;
        ans[++p]=j;
        return true;//继续查找
       }
    return false;//不存在
}
int main()
{
    scanf("%d",&s);
    while(k+n1;
    k+=n;//暴力高斯定理
    do
    {
        if(check(k-s))//暴力判断
         {
            printf("%d\n",n);//输出
            r(i,1,p) printf("%d\n",ans[i]);//暴力输出
            return 0;
         }
        k+=++n;h[n]=1;//继续找
    }while(1);//暴力搜
}

第三题 圆环

思路

一波暴力的辗转相除法,尽管我是用了骚库(STL)

代码

#include
#include
using namespace std;int n,a,b;
int main()
{
    scanf("%d\n%d",&n,&a);//输入
    while(--n)//循环
     scanf("%d",&b),printf("%d/%d\n",a/__gcd(a,b),b/__gcd(a,b));//输出
}

第四题 翻转

思路

暴力模拟
翻转三次,每次对应的格子位置为

x[j][ni+1] x [ j ] [ n − i + 1 ]

x[ni+1][nj+1] x [ n − i + 1 ] [ n − j + 1 ]

x[nj+1][i] x [ n − j + 1 ] [ i ]

当然,也可以直接三次这样子。
x[k1][j][ni+1] x [ k − 1 ] [ j ] [ n − i + 1 ]

代码

#include
#define r(i,a,b) for(int i=a;i<=b;i++)
using namespace std;int n,ans;char c;
bool x[4][501][501];
int make(int k,int i,int j)
{
    if(k==1) return x[0][j][n-i+1];
    if(k==2) return x[0][n-i+1][n-j+1];
    if(k==3) return x[0][n-j+1][i];//一波暴力
}
int main()
{
    scanf("%d",&n);
    r(i,1,n)
    {
        c=getchar();
        r(j,1,n)
        {
            c=getchar();x[0][i][j]=c=='1';ans+=x[0][i][j];
        }//输入不解释
    }
    printf("%d\n",ans);
    r(k,1,3)//翻转三个
    {
        r(i,1,n)
         r(j,1,n)
            if(make(k,i,j)>x[k-1][i][j])
             x[k][i][j]=make(k,i,j),ans++;//如果能够覆盖
            else
             x[k][i][j]=x[k-1][i][j];//否则
        printf("%d\n",ans);//输出
    }
}

第五题 得分

思路

20分思路,dfs
30分思路,贪心
100分思路,动态规划+贪心
动态转移方程

f[j]=max{f[jt[i]+c[i](mj+t[i])} f [ j ] = m a x { f [ j − t [ i ] + c [ i ] ∗ ( m − j + t [ i ] ) }

贪心时间复杂度: O(nlogn+n) O ( n l o g n + n )
贪心空间复杂度: O(2n) O ( 2 n )
动规时间复杂度: O(nlogn+nm) O ( n l o g n + n m )
动规时间复杂度: O(3n) O ( 3 n )

贪心代码

#include
#include
#define r(i,a,b) for(int i=a;i<=b;i++)
using namespace std;int n,m,ans;
struct node
{
    int t,c;
}p[3001];
bool cmp(node x,node y){return x.t/1.0/x.c1.0/y.c;}//按比例排序
int main()
{
    scanf("%d%d",&n,&m);
    r(i,1,n) scanf("%d%d",&p[i].t,&p[i].c);
    stable_sort(p+1,p+1+n,cmp);
    for(int i=1;i<=n;i++)
     if(m>=p[i].t)//一波贪心
      {
        ans+=m*p[i].c;
        m-=p[i].t;
      }
    printf("%d",ans);//输出
}

动态规划代码

#include
#include
#define r(i,a,b) for(int i=a;i<=b;i++)
using namespace std;int n,m,ans,f[10001],tot;
struct node
{
    int t,c;
}p[3001];
bool cmp(node x,node y){return x.t/1.0/x.c1.0/y.c;}
void dp()//动态规划
{
    r(i,1,n)
     for(int j=m;j>=p[i].t;j--)
      if(f[j-p[i].t]+p[i].c*(m-j+p[i].t)>f[j])
       f[j]=f[j-p[i].t]+p[i].c*(m-j+p[i].t);
    r(i,1,m)
     tot=max(f[i],tot);
}
int main()
{
    scanf("%d%d",&n,&m);
    r(i,1,n) scanf("%d%d",&p[i].t,&p[i].c);
    stable_sort(p+1,p+1+n,cmp);//排序这里用了贪心的思想
    dp();
    printf("%d",tot);//输出
}

第六题 重要人物

思路

Spfa+预处理
对于大人物走的路,可以一波预处理,把这些路用一个数组来表示。 lazyi,j.begin l a z y i , j . b e g i n 表示第i个点到第j个点大人物进入的起始时间。 lazyi,j.end l a z y i , j . e n d 表示第i个点到第j个点大人物出去的时间。
然后只需要在spfa里面加上这样一个语句
if(dis[u]>=lazy[u][v].begin i f ( d i s [ u ] >= l a z y [ u ] [ v ] . b e g i n && dis[u]<lazy[u][v].end) d i s [ u ] < l a z y [ u ] [ v ] . e n d )
表示如果这条路大人物会经过的话则

w+=lazy[u][v].enddis[u] w + = l a z y [ u ] [ v ] . e n d − d i s [ u ]

等待大人物

代码

#include
#include
#include/*其实这题用邻接表会更好,但为了练习STL库,还是用了vecotr和queue*/
#include
#define r(i,a,b) for(int i=a;i<=b;i++)
using namespace std;int n,m,A,B,K,G,x,y,w,l[1001][1001],dis[1001],p[1001];//p表示大人物经过的城市
struct node
{
    int begin,end;
}lazy[1001][1001];//一波结构体
vector<int>g[1001];//一波骚库
void spfa()//一波spfa
{
    int from=A;
    queue<int>q;q.push(from);//日常骚库
    bool vis[1001]={0};vis[from]=true;
    dis[from]=K;//这里初始为K,到最后再减
    while(!q.empty())
    {
        int u=q.front();q.pop();vis[u]=true;
        r(i,0,g[u].size()-1)
         {
            int w=l[u][g[u][i]],v=g[u][i];
            if(dis[u]>=lazy[u][v].begin&&dis[u]//骚操作
            if(dis[u]+wif(!vis[v])
                 q.push(v),vis[v]=true;//一波spfa
             }
         }
        vis[u]=false;
    }
}
int main()
{
    scanf("%d%d",&n,&m);
    scanf("%d%d%d%d",&A,&B,&K,&G);//输入
    r(i,0,n-1)
     r(j,i+1,n)
      dis[i]=dis[j]=l[i][j]=l[j][i]=536870912;
    r(i,1,G) scanf("%d",&p[i]);//输入
    r(i,1,m)
    {
        scanf("%d%d%d",&x,&y,&w);
        g[x].push_back(y);
        g[y].push_back(x);
        l[x][y]=l[y][x]=w;//日常spfa
    }
    lazy[p[2]][p[1]].begin=lazy[p[1]][p[2]].begin=0;
    lazy[p[2]][p[1]].end=lazy[p[1]][p[2]].end=l[p[1]][p[2]];
    lazy[p[3]][p[2]].begin=lazy[p[2]][p[3]].begin=lazy[p[1]][p[2]].end;
    lazy[p[3]][p[2]].end=lazy[p[2]][p[3]].end=lazy[p[1]][p[2]].end+l[p[2]][p[3]];
    r(i,4,G)
    {
        lazy[p[i-1]][p[i]].begin=lazy[p[i]][p[i-1]].begin=lazy[p[i-1]][p[i-2]].end;
        lazy[p[i-1]][p[i]].end=lazy[p[i]][p[i-1]].end=lazy[p[i-1]][p[i]].begin+l[p[i-1]][p[i]];
    }//一波lazy操作,只可意会不可言传。
    spfa();//spfa
    printf("%d",dis[B]-K);//输出
}

你可能感兴趣的:(GT,dp,解题报告,总结)