22/5/19

1,dfs剪枝优化:eg1:acwing 165. 小猫爬山;eg2:数独; 2,blocks;3,Sleeping in Class;


1,dfs剪枝优化:

优化策略通常如下:

①优化搜索顺序:大部分情况应该搜索分支少的节点;

②排除等效冗余:尽量不搜索重复的状态;(不考虑顺序的时候,用组合的方式去搜索);

③可行性剪枝:不满足题目要求的分支直接剪掉;

④最优性剪枝:如果当前状态的出的答案一定比已经得到的答案不优,也直接剪掉;

eg1:小猫爬山;

题意:

剪枝策略放代码注释:

优化搜索顺序可以理解一下:优先放重的猫,最有可能把当前的车放满从而减小分支;

(记得之前做oj一道训练题,就差优化搜索顺序给tle了);

#pragma GCC optimize(2)
#include<bits/stdc++.h>
#define rep1(i,a,n) for(register int i=a;i<n;++i) 
#define rep2(i,a,n) for(register int i=a;i<=n;++i) 
#define per1(i,n,a) for(register int i=n;i>a;i--) 
#define per2(i,n,a) for(register int i=n;i>=a;i--)
#define quick_cin() cin.tie(0),cout.tie(0),ios::sync_with_stdio(false)
#define memset(a,i) memset((a),(i),sizeof (a))
#define memcpy(a,i) memcpy((a),(i),sizeof (a))
#define pro_q priority_queue
#define pb push_back
#define pf push_front
#define endl "\n"
#define lowbit(m) (-m&m)
#define YES cout<<"YES\n"
#define NO cout<<"NO\n"
#define Yes cout<<"Yes\n"
#define No cout<<"No\n"
#define yes cout<<"yes\n"
#define no cout<<"no\n"
#define yi first
#define er second
using namespace std;
typedef pair<int,int> PII;
typedef pair<long long,long long>PLL;
typedef pair<int,PII> PIII;
typedef long long ll;
typedef double dob;
const int N=20;
int w[N],sum[N],n,m;
int ans=N;
void dfs(int u,int k)
{
    if(k>=ans)return ;//最优性剪枝
    if(u==n)
    {
        ans=k;
        return ;
    }
    rep1(i,0,k)
    {
        if(sum[i]+w[u]<=m)//可行性剪枝
        {
            sum[i]+=w[u];
            dfs(u+1,k);
            sum[i]-=w[u];//恢复现场
        }
    }
    sum[k]=w[u];//新开一辆车
    dfs(u+1,k+1);
    sum[k]=0;//恢复现场
}
signed main()
{
    quick_cin();
    cin>>n>>m;
    rep1(i,0,n)cin>>w[i];
    sort(w,w+n,greater<int>());//优化搜索顺序
    dfs(0,0);
    cout<<ans;
    return 0;
}

 eg2:数独;

题意:

思路很暴力简单,就是有空的地方找符合条件的数填;

剪枝优化策略:
①优化搜索顺序,填的时候选择分支最少的格子;

②可行性剪枝:只能填满足条件的数字;

还有其他的优化细节:

用长度为9的01串来表示1~9中的数字哪个可以用(当前位置为1即可用,类似状态压缩);

所以求01串的1的位置,不要9个循环一次,用lowbit操作逐个取1(小优化);

求可以填哪个数的时候,就是求行,列,九宫格的01串的交集的1,即hang&lie&cell;

#pragma GCC optimize(2)
#include<bits/stdc++.h>
#define rep1(i,a,n) for(register int i=a;i<n;++i) 
#define rep2(i,a,n) for(register int i=a;i<=n;++i) 
#define per1(i,n,a) for(register int i=n;i>a;i--) 
#define per2(i,n,a) for(register int i=n;i>=a;i--)
#define quick_cin() cin.tie(0),cout.tie(0),ios::sync_with_stdio(false)
#define memset(a,i) memset((a),(i),sizeof (a))
#define memcpy(a,i) memcpy((a),(i),sizeof (a))
#define pro_q priority_queue
#define pb push_back
#define pf push_front
#define endl "\n"
#define lowbit(m) ((-m)&(m))
#define YES cout<<"YES\n"
#define NO cout<<"NO\n"
#define Yes cout<<"Yes\n"
#define No cout<<"No\n"
#define yes cout<<"yes\n"
#define no cout<<"no\n"
#define yi first
#define er second
using namespace std;
typedef pair<int,int> PII;
typedef pair<long long,long long>PLL;
typedef pair<int,PII> PIII;
typedef long long ll;
typedef double dob;
const int N=10,M=1<<N;
int hs[M];
int ones[M],col[N],row[N],cell[3][3];
char s[M];
int get(int x,int y)
{
    return row[x]&col[y]&cell[x/3][y/3];
}
void init()
{
    rep1(i,0,9)row[i]=col[i]=(1<<9)-1;
    rep1(i,0,3)
        rep1(j,0,3)
        cell[i][j]=(1<<9)-1;
}
void draw(int x,int y,int t,bool is_set)
{
    if(is_set)s[x*9+y]='1'+t;
    else s[x*9+y]='.';
    int v=1<<t;
    if(!is_set)v=-v;
    row[x]-=v;
    col[y]-=v; 
    cell[x/3][y/3]-=v;
}
bool dfs(int cnt)
{
    if(!cnt)return 1;
    int minv=10;
    int x,y;
    rep1(i,0,9)
     rep1(j,0,9)
     if(s[i*9+j]=='.')
     {
         int state=get(i,j);
         if(ones[state]<minv)
         {
             x=i,y=j;
             minv=ones[state];
         }
     }
    int state=get(x,y);
    for(int i=state;i;i-=lowbit(i))
    {
        int t=hs[lowbit(i)];
        draw(x,y,t,1);
        if(dfs(cnt-1))return 1;
        draw(x,y,t,0);
    }
    return 0;
}
signed main()
{
    quick_cin();
    rep1(i,0,N)hs[1<<i]=i;
    rep1(i,0,M)
        rep1(j,0,9)
        ones[i]+=i>>j&1;
    while(cin>>s,s[0]!='e')
    {
        init();
        int cnt=0;
        for(int i=0,k=0;i<9;++i)
        {
            for(int j=0;j<9;++j,++k)
            {
                if(s[k]!='.')
                {
                    int t=s[k]-'1';
                    draw(i,j,t,1);
                }
                else cnt++;
            }
        }
        dfs(cnt);
        cout<<s<<endl;
    }
    return 0;
}

2,blocks;

题意:

 思路:直接在6x4的矩阵里找,4重循环,能够找得到就行;

#pragma GCC optimize(2)
#include<bits/stdc++.h>
#define rep1(i,a,n) for(register int i=a;i<n;++i) 
#define rep2(i,a,n) for(register int i=a;i<=n;++i) 
#define per1(i,n,a) for(register int i=n;i>a;i--) 
#define per2(i,n,a) for(register int i=n;i>=a;i--)
#define quick_cin() cin.tie(0),cout.tie(0),ios::sync_with_stdio(false)
#define memset(a,i) memset((a),(i),sizeof (a))
#define memcpy(a,i) memcpy((a),(i),sizeof (a))
#define pro_q priority_queue
#define pb push_back
#define pf push_front
#define endl "\n"
#define lowbit(m) (-m&m)
#define YES cout<<"YES\n"
#define NO cout<<"NO\n"
#define Yes cout<<"Yes\n"
#define No cout<<"No\n"
#define yes cout<<"yes\n"
#define no cout<<"no\n"
#define yi first
#define er second
using namespace std;
typedef pair<int,int> PII;
typedef pair<long long,long long>PLL;
typedef pair<int,PII> PIII;
typedef long long ll;
typedef double dob;
const int N=1e5+10;
string s[10];
int n;
string word;
void solve()
{
    cin>>word;
    unordered_map<char,int>hs1;
    unordered_map<char,int>hs2;
    rep1(i,0,word.size())
    hs1[word[i]]++;
    rep1(i,0,6)
    rep1(j,0,6)
    rep1(k,0,6)
    rep1(m,0,6)
    {
        hs2.clear();
        hs2[s[0][i]]++;
        hs2[s[1][j]]++;
        hs2[s[2][k]]++;
        hs2[s[3][m]]++;
        int len=0;
        while(hs1[word[len]]==hs2[word[len]])
        {
            len++;
            if(len==word.size())
            {
                YES;
                return;
            }
        }
    }
    NO;
}
signed main()
{
    quick_cin();   
    cin>>n;
    rep1(i,0,4)cin>>s[i];
    while(n--)solve();
    return 0;
}

3,sleeping in class;

题意:给你一个数组,你可以将这个数组中的相邻两个数替换为它们的和,设这样为 1 次操作,则进行多少次操作后,数组中所有的数相等。输出最小的操作次数;

因为最终是数组中数都等于一个值,所以可以枚举该值;

一个有sum/x个数,所以合并了n-sum/x次;

#pragma GCC optimize(2)
#include<bits/stdc++.h>
#define rep1(i,a,n) for(register int i=a;i<n;++i) 
#define rep2(i,a,n) for(register int i=a;i<=n;++i) 
#define per1(i,n,a) for(register int i=n;i>a;i--) 
#define per2(i,n,a) for(register int i=n;i>=a;i--)
#define quick_cin() cin.tie(0),cout.tie(0),ios::sync_with_stdio(false)
#define memset(a,i) memset((a),(i),sizeof (a))
#define memcpy(a,i) memcpy((a),(i),sizeof (a))
#define pro_q priority_queue
#define pb push_back
#define pf push_front
#define endl "\n"
#define lowbit(m) (-m&m)
#define YES cout<<"YES\n"
#define NO cout<<"NO\n"
#define Yes cout<<"Yes\n"
#define No cout<<"No\n"
#define yes cout<<"yes\n"
#define no cout<<"no\n"
#define yi first
#define er second
using namespace std;
typedef pair<int,int> PII;
typedef pair<long long,long long>PLL;
typedef pair<int,PII> PIII;
typedef long long ll;
typedef double dob;
const int N=1e5+10;
int n;
int a[N];
ll sum;
bool check(int k)
{
    if(sum%k)return 0;
    ll sum1=0;
    rep2(i,1,n)
    {
        sum1+=a[i];
        if(sum1>k)return 0;
        sum1%=k;
    }
    return 1;
}
void solve()
{
    cin>>n;
    sum=0;
    rep2(i,1,n)
    {
        cin>>a[i];
        sum+=a[i];
    }
    if(!sum)cout<<0<<endl;
    else
    {
        rep2(i,1,sum)
        {
            if(check(i))
            {
                cout<<n-sum/i<<endl;
                return ;
            }
        }
    }
}
signed main()
{
    quick_cin();   
    int T;cin>>T;
    while(T--)solve();
    return 0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Dull丶

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值