2018.10.15 练习赛 搜索专练

Posted katoukatou

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了2018.10.15 练习赛 搜索专练相关的知识,希望对你有一定的参考价值。

T1 乘积分解

题解:

预处理出(n)的约数,用(F[i][j])记录从排序后的第i个因数出发,连续(j)个因数的乘积。 要求(fFi][j]<=n),且(j<=k)

(code):

#include<cstdio>
#include<algorithm>
#include<iostream>
#include<ctype.h>
#include<ctime>
#define ll long long
using namespace std;

char buf[1<<20],*p1,*p2;
inline char gc()
{
//  return getchar();
    return p1==p2&&(p2=(p1=buf)+fread(buf,1,1<<20,stdin))==p1?0:*p1++;
}

template<typename T>
inline void read(T &x)
{
    char tt;
    while(!isdigit(tt=gc()));x=tt-'0';
    while(isdigit(tt=gc())) x=x*10+tt-'0';
}

ll t,n,m,tot;
ll s[100005],fac[100005][30];
double start;
bool dfs(ll x,ll rest,ll fact)
{
    if(!rest) return fact==n;rest--;
    while(x)
    {
        if(x+rest>tot) return 0;
        if(fac[x][rest]>n||fac[x][rest]*fact>n) return 0;
        if(dfs(x+1,rest,fact*s[x])) return 1;x++;
    }
}

int main()
{
    read(t);
    while(t--)
    {
        bool flag=0;
        ll fact=1;
        read(n),read(m);
        if(n==1&&m==2){puts("NIE");continue;}
        if(m<=2)
        {
            puts("TAK");
            continue;
        }
        for(int i=1;i<=m;i++,fact*=i)
        if(fact>n)
        {
            flag=1;
            break;
        }
        if(flag) {puts("NIE");continue;}
        int i;tot=0;
        for (i=1;i*i<n;i++)
        if(n%i==0) s[++tot]=i,s[++tot]=n/i;
        if(i*i==n)s[++tot]=i;
        sort(s+1,s+tot+1);fact=1;
        for(int i=1;i<=tot;i++,fact=1)
        for(int j=0;j<m&&i+j<=tot;j++)
        {
            if(fact<=n) fact*=s[i+j];
            fac[i][j]=fact;
        }
//      for(int i=1;i<=10;i++)
//      printf("%d ",f[3][i]);
        if(dfs(1,m,1)) printf("TAK
");
        else printf("NIE
");
    }
}
//1 1000000000 6

T2 扫雷游戏

题解:

预处理(i),(j)两点穿过的直线,爆搜即可

(code:)

#include<stdio.h>
#include<cstring>
#include<algorithm>
#define lowbit(x) x&-x
using namespace std;

struct node{
    int x,y;
    inline node(int a=0,int b=0)
    {x=a,y=b;}
}a[20];

int n,k;
int f[1<<17],line[20][20];

int dfs(int s)
{
    if(~f[s]) return f[s];
    int cnt=0,t=s;
    while(t) cnt++,t^=lowbit(t);
    if(n-k>=cnt) return f[s]=0;
    if(cnt==1) return f[s]=1;
    f[s]=1e9+9;
    for(int i=0;i<n;i++) if(s>>i&1)
    for(int j=i+1;j<n;j++) if(s>>j&1)
    f[s]=min(f[s],dfs(s&(~line[i][j]))+1);
    return f[s];
}

int main()
{
    for(int t=1;t<=2;t++)
    {
        memset(f,-1,sizeof(f));
        memset(line,0,sizeof(line));
        scanf("%d%d",&n,&k);
        for(int i=0;i<n;i++)
        {
            int x,y;
            scanf("%d%d",&x,&y);
            a[i]=node(x,y);
        }
        //(ay-ky)(ax-bx)==(ax-kx)(ay-by)
        for(int i=0;i<n;i++)
        for(int j=0;j<n;j++) if(i!=j)
        for(int k=0;k<n;k++)
        if((a[i].y-a[k].y)*(a[i].x-a[j].x)==(a[i].x-a[k].x)*(a[i].y-a[j].y))
        line[i][j]|=(1<<k);
     printf("%d
",dfs((1<<n)-1));
    }
}

T3 数字消除游戏

题解:

A*+迭代加深+扩展周围有的颜色+不真实赋值,标记联通性

(code:)

#include<cstdio>
#include<algorithm>
#include<iostream>
#include<cmath>
#include<stdlib.h>
#include<ctype.h>
#define eps 1e-7
#define ll long long
using namespace std;

char buf[1<<20],*p1,*p2;
inline char gc()
{
    return getchar();
    return p1==p2&&(p2=(p1=buf)+fread(buf,1,1<<20,stdin))==p1?0:*p1++;
}

template<typename T>
inline void read(T &x)
{
    char tt;
    while(!isdigit(tt=gc()));x=tt-'0';
    while(isdigit(tt=gc())) x=x*10+tt-'0';
}

int n;
int a[10][10],book[10][10];
int dx[4]={0,0,1,-1},dy[4]={1,-1,0,0};
bool cl[10];
int gujia()
{
    int col=0;
    for(int i=0;i<=5;i++) cl[i]=0;
    for(int i=1;i<=n;i++)
    for(int j=1;j<=n;j++)
    if(!cl[a[i][j]]&&book[i][j]!=1)
    {
        cl[a[i][j]]=1;
        col++;
    }
    return col;
}

void dfs(int x,int y,int c)
{
    book[x][y]=1;
    for(int i=0;i<4;i++)
    {
        int tx=x+dx[i],ty=y+dy[i];
        if(tx<=0||ty<=0||tx>n||ty>n) continue;
        if(book[tx][ty]==1) continue;
        
        book[tx][ty]=2;
        if(a[tx][ty]==c) dfs(tx,ty,c);
    }
}

int fill(int c)
{
    int sum=0;
    for(int i=1;i<=n;i++)
    for(int j=1;j<=n;j++)
    if(a[i][j]==c&&book[i][j]==2)
    {
        sum++;
        dfs(i,j,c);
    }
    return sum;
}

bool astar(int dep,int maxdep)
{
    int g=gujia();
    if(dep+g>maxdep) return 0;
    if(!g) return 1;
    int temp[10][10];
    for(int i=0;i<=5;i++)
    {
        for(int c=1;c<=n;c++)
        for(int j=1;j<=n;j++)
        temp[c][j]=book[c][j];
        
        if(fill(i)&&astar(dep+1,maxdep)) return 1;
        
        for(int c=1;c<=n;c++)
        for(int j=1;j<=n;j++)
        book[c][j]=temp[c][j];
    }
    return 0;
}

int main()
{
    while(1)
    {
        read(n);
        if(!n) return 0;
        for(int i=1;i<=n;i++)
        for(int j=1;j<=n;j++)
        read(a[i][j]);
        
        for(int i=1;i<=n;i++)
        for(int j=1;j<=n;j++)
        book[i][j]=0;
        
        dfs(1,1,a[1][1]);
        for(int dep=0;;dep++)
        if(astar(0,dep)) 
        {   
            printf("%d
",dep);
            break;
        }
    }
}

以上是关于2018.10.15 练习赛 搜索专练的主要内容,如果未能解决你的问题,请参考以下文章

2018.10.18 练习赛 数学专练

2018.10.10 练习赛 状态压缩专练(T4-T5)

三月专题Dp专练

二叉树刷题专练

从搜索文档中查找最小片段的算法?

2018.10.15队测