Solution de pression dp

Solution numérique dp:

A. Damier spécial

  • Titre: Mettez une voiture sur le damier dans \ (n \ fois n \)n , certaines cases ne peuvent pas être placées, et recherchez le nombre total de solutions qui les empêchent de s'attaquer. Remarque: Il ne peut y avoir qu'une seule voiture dans la même ligne ou colonne, sinon ils s'attaqueront mutuellement.

  • Analyse:

    • Tout d'abord, il ne peut y avoir qu'une seule voiture par ligne, tant que chaque ligne est placée une ligne à la fois pour s'assurer qu'il n'y a pas d'attaque entre la même ligne.
    • Deuxièmement, une seule voiture peut être placée dans chaque colonne, tant qu'elle peut enregistrer quelle colonne a une voiture, il ne sera pas nécessaire de considérer cette colonne la prochaine fois.
    • Utilisez un nombre binaire Spour indiquer si une voiture a été placée dans une colonne. Par exemple n=5, S=01101, cela signifie que les première, troisième et quatrième colonnes (à partir de la position inférieure) ont placé des voitures. On retrouve enfin S=11111le nombre de solutions en l'état .
    • La définition f[s]représente le snombre de scénarios dans l'état . \ (s \ dans [0 \ sim 2 ^ n-1] \)
      • Supposons s=01101, évidemment:f[01101]= f[01100]+f[01001]+f[00101]
      • Mais qu'en est-il s'il y a un obstacle à l'emplacement actuel? Donc, lorsque nous remettons la voiture, nous jugeons s'il y a un obstacle dans la position actuelle. Voir le code pour une implémentation spécifique.
  • Implémentation du code:

    #include<bits/stdc++.h>
    const int maxn=(1<<20)-1;
    typedef long long LL;
    LL f[maxn],a[25];//a[x]记录第x行的障碍状态
    int lowbit(int x){return x & -x;};
    int main(){
        int n,m;scanf("%d%d",&n,&m);
        for(int i=1;i<=m;++i){
            int x,y;scanf("%d%d",&x,&y);
            a[x]+=1<<(y-1);
        }
        f[0]=1;//一个也不放也是一种方案
        int maxs=1<<n;//最大的状态
        for(int S=1;S<maxs;++S){//从状态1开始枚举
            int cnt=0;//计算状态S里的1的个数,几个1说明处理到第几行
            for(int i=S;i;i-=lowbit(i))cnt++;
            for(int i=S;i;i-=lowbit(i)){//依次判断当前状态每一个1
                if(!(a[cnt] & lowbit(i))){//状态S当前的1所在列如果没有障碍
                    int s=S^lowbit(i);//说明lowbit(i)处可以放车,当前就在此处放车
                    f[S]+=f[s];//s<S,保证能转移
                }
            }
        }
        printf("%lld\n",f[maxs-1]);
        return 0;
    }
    

B. Non-agression

  • Signification des questions: dans \ (n \ times n \) Conseil qui a mis nun roi, afin qu'ils n'attaquent pas, mettre le nombre total de programme espèces. Le roi peut l'attaquer en haut, en bas, à gauche, à droite, en haut à gauche, en bas à droite, en haut à droite, en bas à droite et une grille dans chacune des huit directions à proximité, pour un total de grilles.
  • Analyse:
    • Cette question est très similaire à l'exemple du champ de maïs dont nous avons parlé. Il y a moins d'obstacles, mais la limite de nombre est augmentée. En général, s'il y a une autre limite, nous augmenterons l'état unidimensionnel.
    • Que l' état de placement du roi au dp[ i ][ j ][ k ]premier i rang soit le jnombre kde plans sur le plateau .
    • L'étape est évidente, c'est-à-dire que nous pouvons la traiter ligne par ligne, la première ligne est spéciale, nous pouvons prétraiter
    • Conflit de jugement: supposez que sla ligne actuelle s'est la ligne précédente.
      • Les conflits de lignes, c'est-à-dire ne peuvent pas être adjacents, il suffit de juger (s & (s<<1))==0, non nul signifie qu'il y a adjacent.
      • Conflit de colonne:
        • Conflit à l'envers: juge (s & s')==0, sinon 0, cela signifie conflit à l'envers.
        • Conflit supérieur gauche: juge ((s<<1) & s')==0, sinon 0, expliquez le conflit.
        • Conflit supérieur droit: juge ((s>>1) & s')==0, sinon 0, expliquez le conflit.
      • Pour déterminer 1le nombre d'états dans l' état actuel , utilisez lowbit.

Je suppose que tu aimes

Origine www.cnblogs.com/hbhszxyb/p/12710188.html
conseillé
Classement