HMOI 2018 南京暑假集训期末考试总结

Posted lyfoi

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了HMOI 2018 南京暑假集训期末考试总结相关的知识,希望对你有一定的参考价值。

A POJ 1717 Dominoes

翻译

题目给出两列数,为了使两列数的和之间的差距变小,可以交换对应位置的数字,求出当最小的时候,最少的交换次数。

思路

签到题目,但是我还是太菜了,竟然没有看出是背包。

(dp_{i,j})代表前(i)个使得差异值为(j)的最少翻转次数,至少(12000)。边界问题由于点最多为(6)个,最小为(1)个,加之可能出现负数,那么数组大小至少要到((6-1)*60-0*2=12000)

然后我们直接枚举从小到大(dp_{n,j})(j)就是可能出现的数,然后找到第一个(dp)数组更新过的答案,然后输出负数或者正数差的最小值即可。

Code

#include<algorithm>
#include<iostream>
#include<cstring>
#include<cmath>
using namespace std;
int n,up[1001],down[1001],dp[1001][15001];
int main()
{
    memset(dp,0x7f,sizeof(dp));
    cin>>n;
    for(int i=1; i<=n; i++)
        cin>>up[i]>>down[i];
    dp[0][6000]=0;
    for(int i=1; i<=n; i++)
        for(int j=0; j<=15000; j++)
            dp[i][j]=min(dp[i-1][j-up[i]+down[i]],dp[i-1][j+up[i]-down[i]]+1);
    for(int i=0; i<=6000; i++)
        if(min(dp[n][i+6000],dp[n][6000-i])<=1000)
            return cout<<min(dp[n][i+6000],dp[n][6000-i])<<endl,0;
    return 0;
}

B CF543A Writing Code

翻译

(n)程序员,每个程序员可以写若干行代码,第(i)个程序员每行里会有 (a_i)(bug),现在要完成一个恰好(m)行的代码且总(bug)数量不能超过 (b),求有多少种完成方案。两种方案不同当且仅当某个程序员在两种方案中完成的行数不同。答案模给定的数。

思路

咕咕咕!

(dp_{i,j,k})表示让前(i)个人完成(j)页文本并且问题不超过(k)的方案数,那么有:

[dp_{i,j,k}=dp_{i-1,j,k}+dp_{i-1,j-1,k-a_i}]

注意取模,这道题可以用滚动数组优化哦。

Code


#include<bits/stdc++.h>
using namespace std;
int n,m,b,mod;
int a[501],dp[501][501];
int main()
{
    
    cin>>n>>m>>b>>mod;
    for(int i=1;i<=n;i++) 
        cin>>a[i];
    for(int i=0;i<=b;i++) 
        dp[0][i]=1;
    for(int i=1;i<=n;i++)
        for(int j=1;j<=m;j++)
            for(int k=a[i];k<=b;k++) 
                dp[j][k]=(dp[j][k]+dp[j-1][k-a[i]])%mod;
    cout<<dp[m][b]<<endl;
    return 0;
}

C Ural 1325 Dirt

翻译

从冰箱的地方去电脑的地方找到一条换鞋的次数最少并且在换鞋次数最少的基础上找到一条最短路。换鞋的规则如下:

  • 从干净的地方去脏的地方要换鞋,反之亦然。

  • 从脏的地方去脏的地方不用换鞋,干净去干净的地方也不用。

Code

我还是那么的菜辣,还以为这道题是动归呜呜呜!

实际上这道题稍微有那么一点点在时间和空间卡你,于是许多人写炸了。两种做法,一种 0-1 BFS(脏的地方去干净或干净的地方去脏的有代价,否则没有),另一种直接跑最短路,算了别想双端队列,来发 Dijstra,不堆优化是会 (TLE)哦!

Code

#include<bits/stdc++.h>
using namespace std;
const int INF=2e9;
int sx,sy,ex,ey;
int fx[8]={0,0,1,-1,1,1,-1,-1};
int fy[8]={1,-1,0,0,1,-1,1,-1};
char edge[501][501];
bool vis[501][501];
int n,m;
struct node
{
    int x,y;
    int step,change;
    friend bool operator < (node a,node b)
    {
        if(a.change==b.change)
            return a.step>b.step;
        return a.change>b.change;
    }
}book[501][501];

void bfs(int sx,int sy)
{
    vis[sx][sy]=true;
    book[sx][sy].step=1;
    book[sx][sy].change=0;
    priority_queue<node> q;
    q.push(book[sx][sy]);
    while(!q.empty())
    {
        node cur=q.top();
        q.pop();
        for(int i=0; i<8; i++)
        {
            int nx=cur.x+fx[i];
            int ny=cur.y+fy[i];
            if(nx<0||nx>=n||ny<0||ny>=m||edge[nx][ny]=='0')
                continue;
            vis[nx][ny]=true;
            node next;
            next.x=nx; next.y=ny;
            if(edge[nx][ny]!=edge[cur.x][cur.y]) next.change=cur.change+1;
            else next.change=cur.change;
            next.step=cur.step+1;
            if(book[nx][ny]<next)
            {
                book[nx][ny]=next;
                q.push(next);
            }
        }
    }
}
int main()
{
    cin>>n>>m;
    cin>>sx>>sy>>ex>>ey;
    for(int i=0; i<n; i++)
        for(int j=0; j<m; j++)
        {
            vis[i][j]=false;
            cin>>edge[i][j];
            book[i][j].x=i;
            book[i][j].y=j;
            book[i][j].change=INF;
            book[i][j].step=INF;
        }
    bfs(sx-1,sy-1);
    if(vis[ex-1][ey-1])
        cout<<book[ex-1][ey-1].step<<" "<<book[ex-1][ey-1].change<<endl;
    else
        cout<<0<<" "<<0<<endl;
    return 0;
}

以上是关于HMOI 2018 南京暑假集训期末考试总结的主要内容,如果未能解决你的问题,请参考以下文章

大暑假集训总结(反思)

[补档]暑假集训D3总结

暑假集训D18总结

暑假集训D9总结

暑假集训D11总结

[补档]暑假集训D8总结