2018.6.17 题解HGOI

今天做的是11年day1的真题

  • 由于我平时比较懒所以真题真的不怎么做(小声bb,千万不能被教练发现
  • 但确实day1的题比较简单。

第一题——铺地毯(carpet)

  • 这道真的很水的,数据量也没有多少(只有一万)
  • 首先小学生都知道这道题不可能用每个点的模拟更新来做
  • 那干脆直接把这个图存下来,再单点查询就好了

#include <iostream>
#include <cstdio>
#include <algorithm>
#include <cstring>
#include <vector>
#include <cmath>
using namespace std;
void fff(){
    freopen("carpet.in","r",stdin);
    freopen("carpet.out","w",stdout);
}
const int MAXN=10100;
struct node{
    int x1,x2,y1,y2;
}a[MAXN];
int n,goal_x,goal_y,ans;
bool check(int x){
    if(a[x].x1>goal_x||a[x].x2<goal_x) return false;
    if(a[x].y1>goal_y||a[x].y2<goal_y) return false;
    return true;
}
int main(){
    fff();
    ans=-1;
    scanf("%d",&n);
    for (int i=1;i<=n;i++){
        int g,k;
        scanf("%d%d%d%d",&a[i].x1,&a[i].y1,&g,&k);
        a[i].x2=a[i].x1+g;
        a[i].y2=a[i].y1+k;
    }
    scanf("%d%d",&goal_x,&goal_y);
    for (int i=1;i<=n;i++){
        if(check(i)) ans=i;
    }
    printf("%d",ans);
}

第二题——选择客栈(hotel)

  • 这是一道类似于dp的题,问你两个相同颜色之间的点(包含)是否有值小于等于目标值
  • 讲道理这道题也是很水的。
  • 打一把st算出两点之间是否有合法值
  • 读入的时候把相同颜色的存下来然后枚举查询
  • 然后就AC

#include <iostream>
#include <cstdio>
#include <algorithm>
#include <cstring>
#include <vector>
#include <cmath>
using namespace std;
void fff(){
    freopen("hotel.in","r",stdin);
    freopen("hotel.out","w",stdout);
}
const int MAXN=200100;
vector <int> color[51];
struct node{
    int color_num,prize;
}a[MAXN];
int n,k,p;
int m[MAXN][21];
void st(){
    memset(m,0,sizeof(m));
    for (int i=1;i<=n;i++) if(a[i].prize<=p) m[i][0]=1;
    for (int j=1;(1<<j)<=n;j++){
        for (int i=1;i+(1<<j)-1<=n;i++){
            m[i][j]=m[i][j-1]+m[i+(1<<(j-1))][j-1];
        }
    }
}
int Query(int x,int y){
    if(x>y) swap(x,y);
    int k=(log(y-x+1)/log(2));
    int temp=0;
    return (m[x][k]+m[y-(1<<k)+1][k]);
}
int main(){
    int ans=0;
//  fff();
    scanf("%d%d%d",&n,&k,&p);
    for (int i=1;i<=n;i++){
        scanf("%d%d",&a[i].color_num,&a[i].prize);
        color[a[i].color_num].push_back(i);
    }
    st();
    for (int i=0;i<=k;i++){
        int s=color[i].size();
        for (int j=0;j<s-1;j++){
            int t=j+1;
            while (true){
                int tt=color[i][j],b=color[i][t];
                if(Query(tt,b)>0) break;
                t++;
            }
            ans+=(s-t);
        }
    }
    cout<<ans;
}

第三题——Mayan游戏(mayan)

  • 一看这个数据量我就知道这个是深搜题,不过状态刚开始不知道怎么存,就有点尴尬(只靠输出-1打了两个点)
  • 无脑深搜,外存状态吧(具体怎么存就看代码吧)。再剪下枝就可以过了。
  • 剪枝有以下几个方面去考虑:
    • 首先如果对于一个点左边有值那他就不用再往左搜索(之前就做过往右了,换一下效果一样,唯一不同就是TEL…)
    • 第二,如果存在一个状态有数值只剩下两个就一定消不掉(但这个我其实没有判因为省不了多少时间。)
    • 第三两个一样的块是不会交换的(效果真的真的一样。)
  • 一百行的深搜真的很少打,要好好学习代码实现了。

#include <iostream>
#include <cstdio>
#include <algorithm>
#include <cstring>
#include <vector>
#include <cmath>
#include <queue>
#include <stack>
using namespace std;
void fff(){
    freopen("mayan.in","r",stdin);
    freopen("mayan.out","w",stdout);
}
const int MAXN=99999;
int n;
int map[7][5][7];
int ansx[10],ansy[10],ansg[10];
bool visited[5][7];
void fall(int step){
    for (int i=0;i<5;i++){
        int sz=0;
        for (int j=0;j<7;j++){
            if(map[step][i][j]) map[step][i][sz++]=map[step][i][j];
        }
        while (sz<7) map[step][i][sz++]=0;
    }
}
void mv(int step){
    int tim=0;
    bool cg=true;
    while (cg){
        cg=false;
        fall(step);
        for (int i=0;i<5;i++)
            for (int j=0;j<7;j++)
                if(map[step][i][j]){
                    if (i<3){
                        if(map[step][i][j]==map[step][i+1][j]&&map[step][i][j]==map[step][i+2][j]){
                            cg=visited[i][j]=visited[i+1][j]=visited[i+2][j]=true;
                        }
                    }
                    if (j<5){
                        if(map[step][i][j]==map[step][i][j+1]&&map[step][i][j]==map[step][i][j+2]){
                            cg=visited[i][j]=visited[i][j+1]=visited[i][j+2]=true;
                        }
                    }
                }
        for (int i=0;i<5;i++)
            for (int j=0;j<7;j++){
                if(visited[i][j]) map[step][i][j]=visited[i][j]=0;
            }
    }
}
bool dfs(int step){
    for (int i=0;i<5;i++){
        for (int j=0;j<7;j++){
            map[step][i][j]=map[step-1][i][j];
        }
    }
    mv(step);
    if(step==n+1){
        for (int i=0;i<5;i++) if(map[step][i][0]) return false;
        return true;
    }
    for (int i=0;i<5;i++)
        for (int j=0;j<7;j++){
            if(map[step][i][j]){
                if(i<4&&map[step][i][j]!=map[step][i+1][j]){
                    ansx[step]=i,ansy[step]=j,ansg[step]=1;
                    swap(map[step][i][j],map[step][i+1][j]);
                    if(dfs(step+1)) return true;
                    swap(map[step][i][j],map[step][i+1][j]);
                }
                if(i&&(map[step][i-1][j]==0)){
                    ansx[step]=i,ansy[step]=j,ansg[step]=-1;
                    swap(map[step][i][j],map[step][i-1][j]);
                    if(dfs(step+1)) return true;
                    swap(map[step][i][j],map[step][i-1][j]);
                }
            }
        }
    return false;
}
int main(){
    fff();
    scanf("%d",&n);
    memset(map,0,sizeof(map));
    for (int i=0;i<5;i++){
        int t,k=0;
        while (scanf("%d",&t)&&t!=0){
            map[0][i][k++]=t;
        }
    }
    if(dfs(1)){
        for (int i=1;i<=n;i++){
            cout<<ansx[i]<<' '<<ansy[i]<<' '<<ansg[i]<<'\n';
        }
    }else{
        cout<<-1;
    }
}

猜你喜欢

转载自blog.csdn.net/qq_42037034/article/details/80719396