搜索

搜索大法好

 

小木棍:https://www.luogu.org/problem/P1120

这数据也太加强了吧qaq

优化:对木棍排序,显然先用长度大的;枚举可能长度时,可能长度是总长度的因数

然后就是重头戏:如果在一开始,你加入当前最大的木棍,然后你失败了,那么目前为止的方案肯定就不行了,因为这个最大木棍再也没有被用的机会了

同理,如果你用当前最大填满了,在下一轮中你又失败了,这个肯定也不行

还有要记得unique啥的,不然扩展层数太多

#include<cstdio>
#include<iostream>
#include<algorithm>
#include<cstring>
#include<queue>
#include<map>
using namespace std;
typedef long long ll;
//typedef int mainint;
//#define int long long
typedef double db;
#define pii pair<int,int>
#define mp make_pair
#define llinf 9000000000000000000LL
#define inf 0x3f3f3f3f
#define B cout << "breakpoint" << endl;
#define clr(a) memset(a,0,sizeof(a));
#define O(x) cout << #x << " "  << (x) << endl; 
inline int read()
{
    int ans = 0,op = 1;
    char ch = getchar();
    while(ch < '0' || ch > '9')
    {
        if(ch == '-') op = -1; 
        ch = getchar();
    }
    while(ch >= '0' && ch <= '9')
    {
        (ans *= 10) += ch - '0';
        ch = getchar();
    }
    return ans * op;
}
int n,a[100],sum,L,tot;
bool flag,ok;
int vis[101];
bool cmp(int a,int b) { return a > b; }
void dfs(int cur,int len,int tot)
{
    //if(L == 6) printf("%d %d %d\n",cur,len,tot);
    if(tot == 0) 
    {
        printf("%d",L);
        exit(0);
    }
    else if(cur == n + 1 && len == L) return (void)dfs(1,0,tot - 1);
    for(int i = cur;i <= n;i++)
    {
        if(!vis[a[i]]) continue;
        if(len + a[i] > L) continue;
        vis[a[i]]--;
        if(len + a[i] == L) dfs(1,0,tot - 1);
        else dfs(i,len + a[i],tot);
        vis[a[i]]++;
        if(len == 0 || len + a[i] == L) return;
    }
}
int main()
{
    n = read();
    int mx = 0;
    for(int i = 1;i <= n;i++)     
    { 
        int x = read(); if(x > 50) continue;
        a[++tot] = x;
        vis[x]++;
        sum += a[tot],mx = max(a[tot],mx);
    }
    n = tot;
    sort(a + 1,a + 1 + n,cmp);
    tot = unique(a + 1,a + 1 + n) - a - 1;
    n = tot;
    for(int i = mx;i <= sum;i++)
    {
        if(sum % i) continue;
        L = i;
        ok = flag = 0;
        dfs(1,0,sum / i);
    }
}
View Code

 

N皇后:https://www.luogu.org/problem/P1562

维护三个状态:列、左对角线,右对角线,二进制维护

每到下一层,左对角线左移,右对角线右移(画图即可

#include<cstdio>
#include<iostream>
#include<algorithm>
#include<cstring>
#include<queue>
#include<map>
using namespace std;
typedef long long ll;
//typedef int mainint;
//#define int long long
typedef double db;
#define pii pair<int,int>
#define mp make_pair
#define llinf 9000000000000000000LL
#define inf 0x3f3f3f3f
#define B cout << "breakpoint" << endl;
#define clr(a) memset(a,0,sizeof(a));
#define O(x) cout << #x << " "  << (x) << endl; 
inline int read()
{
    int ans = 0,op = 1;
    char ch = getchar();
    while(ch < '0' || ch > '9')
    {
        if(ch == '-') op = -1; 
        ch = getchar();
    }
    while(ch >= '0' && ch <= '9')
    {
        (ans *= 10) += ch - '0';
        ch = getchar();
    }
    return ans * op;
}
int n,a[101];
int last,ans;
inline int lowbit(int x) { return x & (-x); }
void dfs(int cur,int col,int sl,int sr)
{
    if(cur == n + 1) return (void)(ans += (col == last));
    int pos = (~(col | sl | sr | a[cur])) & last;
    while(pos)
    {
        int p = lowbit(pos);
        pos = pos ^ p;
        dfs(cur + 1,col | p,(sl | p) << 1,(sr + p) >> 1);
    }
}
int main()
{
    n = read();
    last = (1 << n) - 1;
    for(int i = 1;i <= n;i++)
        for(int j = 1;j <= n;j++)
        {
            a[i] <<= 1;
            char c;
            cin >> c;
            if(c == '.') a[i] |= 1;
        }
    dfs(1,0,0,0);
    printf("%d",ans);
}
        
View Code

 

骑士精神:https://www.luogu.org/problem/P2324

假的A*

考虑下界剪枝,设置估价函数e,IDA*即可

#include<cstdio>
#include<iostream>
#include<algorithm>
#include<cstring>
#include<queue>
#include<map>
using namespace std;
typedef long long ll;
//typedef int mainint;
//#define int long long
typedef double db;
#define llinf 9000000000000000000LL
#define inf 0x3f3f3f3f
#define B cout << "breakpoint" << endl;
#define clr(a) memset(a,0,sizeof(a));
#define O(x) cout << #x << " "  << (x) << endl; 
inline int read()
{
    int ans = 0,op = 1;
    char ch = getchar();
    while(ch < '0' || ch > '9')
    {
        if(ch == '-') op = -1; 
        ch = getchar();
    }
    while(ch >= '0' && ch <= '9')
    {
        (ans *= 10) += ch - '0';
        ch = getchar();
    }
    return ans * op;
}
const int dx[]={0,1,1,-1,-1,2,2,-2,-2};
const int dy[]={0,2,-2,2,-2,1,-1,1,-1};
const int goal[7][7]={
    {0,0,0,0,0,0},
    {0,1,1,1,1,1},
    {0,0,1,1,1,1},
    {0,0,0,2,1,1},
    {0,0,0,0,0,1},
    {0,0,0,0,0,0}
};
bool ok;
int mp[7][7];
inline int e()
{
    int res = 0;
    for(int i = 1;i <= 5;i++)
        for(int j = 1;j <= 5;j++)
            if(mp[i][j] != goal[i][j]) res++;
    return res;
}
void dfs(int dep,int x,int y,int mdep)
{
    if(dep == mdep) return (void)(ok = (e() == 0));
    for(int i = 1;i <= 8;i++)
        {
            if(ok) return;
            int nx = x + dx[i],ny = y + dy[i];
            if(nx < 1 || nx > 5 || ny < 1 || ny > 5) continue;
            swap(mp[x][y],mp[nx][ny]);
            if(dep + e() <= mdep) dfs(dep + 1,nx,ny,mdep);
            swap(mp[x][y],mp[nx][ny]);
        }    
}
int main()
{
    int t = read();
    while(t--)
    {
        ok = 0;
        int sx,sy;
        char x;
        for(int i = 1;i <= 5;i++)
            for(int j = 1;j <= 5;j++)
            {
                cin >> x;
                if(x == '*') mp[i][j] = 2,sx = i,sy = j;
                else mp[i][j] = x - '0';
            }
        if(!e()) {printf("0\n"); continue; }
        for(int i = 1;i <= 15;i++)
        {
            dfs(0,sx,sy,i);
            if(ok)
            {
                printf("%d\n",i);
                break;
            }
        }
        if(!ok) printf("-1\n");
    }
}
View Code

 

posted on 2019-07-28 14:53  L_M_A  阅读(161)  评论(0编辑  收藏  举报

导航