Jeanny
寂兮,寥兮,独立不改,周行而不殆

过河

#include <bitsstdc++.h>
using namespace std;
const int N = (1<<16) + 5;
int n, dp[N], t[N], w[N],m;
int main() {
    cin>>m>>n;
    memset(dp, 0x3f, sizeof dp); dp[0] = 0;
    for(int i = 0; i < n; i++){
        cin>>t[1<<i]>>w[1<<i];
        dp[1<<i] = t[1<<i];
    }
    for(int i = 0; i <= (1 << n)-1; i++){
        //w[i] = w[i ^ p] + w[p] 递推公式,"110",p=10, w[110] = w[100] + w[10] 从小到大的顺序肯定能推出来
        int p = (i & -i);
        w[i] = w[i ^ p] + w[p], t[i] = max(t[i ^ p], t[p]);
        for(int j = i; j ; j = (j-1) & i){
            if(w[j] <= m)
                dp[i] = min(dp[i], dp[i^j] + t[j]); //问题,*** 这个地方是难点,还可以在外面判断一下if(w[i] <= m) dp[i] = t[i]; ***
            if(w[j^i] <= m)
                dp[i] = min(dp[i], dp[j] + dp[i^j]);
        }
    }
    cout<<dp[(1<<n) - 1]<<endl;
    return 0;
}

八人过河

#include<bitsstdc++.h>
using namespace std;
int b[] = {0, 0, 0, 0, 0, 1, 1, 1, 0}, vis[300][300][3];
/*
  8 7 6 5 4 3 2 1
  c p f m b b g g
  1 1 1 1 1 1 1 1
& 1 0 
-----------------
&     1 0     1
&     1 0       1
&     1 0     1 1
&     0 1 1
&     0 1 0 1
      0 1 1 1

*/
int chk(int ls){
            // if(ls & 11000000 == 10000000) if(ls & 00111111 > 0) 犯人在警察不在且还有其他人
    if((ls & 192) == 128 && (ls & 63) > 0) return 0; 
           // if(ls & 110011  -  100011) //爸爸在妈妈不在,女儿在
    if((ls & 51) >= 33 && (ls & 51) <= 35) return 0;
            // if(ls & 111100 > 011100)//妈妈在爸爸不在,儿子在
    if((ls & 60) == 28 || (ls & 60) == 24 || (ls & 60) == 20) return 0;
    return 1;
}
int ans = INT_MAX, s[3],go[105][3],bk[105][3],lb[105][3],lg[105][3],rid[105], id[105];
void print(int x){
    int s[15], t = 0;
    memset(s, 0, sizeof s);
    while(x){
        s[++t] = (x&1);
        x >>= 1;
    }
    for(int i = 8; i >= 1; i--)
        cout<<s[i];
}
void dfs(int t, int ls, int rs, int r, int peo){//11101100
    // cout<<endl;
    // cout<<"ls,rs: "<<ls<<" "<<rs<<endl;
    // if(t >= 11) return; 
     int s[3] = {ls, rs};//s[0] = ls, s[1] = rs;
    // if(chk(ls) == 0 || chk(rs) == 0) return;
    // cout<<"t1: "<<t<<endl;
    // cout<<ls<<" ";print(ls);cout<<" , "; cout<<rs<<" ";print(rs);cout<<endl;
   
    // cout<<"ls, rs : "<<ls<<" "<<rs<<endl;
    // cout<<"rrrrrrr: "<<r<<" ,t: "<<t<<" "<<endl;
    if(ls == 0 && rs == 255){
        if(t < ans){
            ans = t;
            for(int i = 1; i <= t; i++){
                id[i] = rid[i], lg[i][1] = go[i][1], lg[i][2] = go[i][2], lb[i][1] = bk[i][1], lb[i][2] = bk[i][2];
            }   
        }
        return;
    //    ans = min(ans, t);
       
    }
    // cout<<"r:"<<r<<endl;
    if(r == 1)
        for(int i = 1; i <= 8; i++){  
            if(b[i] == 0) continue;//成年人非犯人可以过河
            if((1 << (i - 1) & s[r]) == 0) continue;//i这个人在   
            if(chk(s[r] & ~(1 <<(i-1))) && chk(s[r^1] | (1 <<(i-1)))) {
                // cout<<"回—i: "<<i<<" "<<r<<endl;
                // cout<<endl;
                //回来之后该去右边了
                // cout<<(s[r^1] | (1 <<(i-1)))<<" "<<(s[r] & ~(1 <<(i-1)))<<" "<<vis[s[r^1] | (1 <<(i-1))][s[r] & ~(1 <<(i-1))][r^1]<<endl;
                if(vis[s[r^1] | (1 <<(i-1))][s[r] & ~(1 <<(i-1))][r^1] == 1) continue;
                vis[s[r^1] | (1 <<(i-1))][s[r] & ~(1 <<(i-1))][r^1] = 1;
                if(peo == i) continue;
                rid[t+1] = r;
                bk[t+1][1] = i; bk[t+1][2] = 0;
                dfs(t+1, s[r^1] | (1 <<(i-1)), s[r] & ~(1 <<(i-1)),  r^1, i);
                vis[s[r^1] | (1 <<(i-1))][s[r] & ~(1 <<(i-1))][r^1] = 0;
            }
        }
    for(int i = 1; i < 8; i++){//0 1 1 1 1 1 1 1
        if(((1 << (i - 1)) & s[r]) == 0) continue;//i这个人在
        for(int j = i+1; j <= 8; j++){
            if((1 << (j - 1) & s[r]) == 0) continue;
            if(peo == i*10+j) continue;
            // cout<<ls<<" ";print(ls);cout<<" , "; cout<<rs<<" ";print(rs);cout<<endl;
            if(b[i] == 0 && b[j] == 0) continue;
            // cout<<i<<"  ___ "<<j<<endl;
            // cout<<chk(s[r] & ~(1 <<(i-1)) & ~(1 << (j-1))) <<endl;
            // cout<<chk(s[r^1] | (1 <<(i-1)) | (1 <<(j-1)))<<endl;
            // cout<<"r: "<<r<<endl;
            //不是小孩和犯人
            // cout<<"1,i,j: "<<i<<" "<<j<<endl;
            if(chk(s[r] & ~(1 <<(i-1)) & ~(1 << (j-1))) && chk(s[r^1] | (1 <<(i-1)) | (1 <<(j-1)))) {
                // cout<<i<<"  ___ "<<j<<endl;
                // cout<<"peo: "<<peo<<endl;
                // cout<<"tt,r:"<<t<<" "<<r<<endl;
                // print(s[r^1]);cout<<" ";print(s[r]);cout<<endl;
                // print(ls);cout<<" ";print(rs); cout<<endl;
                // cout<<"r_change:"<<r<<endl;
                if(r == 0){
                    // cout<<"ppp : "<<(s[r] & ~(1 <<(i-1)) & ~(1 << (j-1)))<<" "<<(s[r^1] | (1 <<(i-1)) | (1 <<(j-1)))<<endl;
                    if(vis[s[r] & ~(1 <<(i-1)) & ~(1 << (j-1))][ s[r^1] | (1 <<(i-1)) | (1 <<(j-1))][r^1] == 1) continue;
                    vis[s[r] & ~(1 <<(i-1)) & ~(1 << (j-1))][ s[r^1] | (1 <<(i-1)) | (1 <<(j-1))][r^1] = 1;
                    if(peo == i*10+j) continue;
                    rid[t+1] = r;
                    go[t+1][1] = i, go[t+1][2] = j; 
                    dfs(t+1, s[r] & ~(1 <<(i-1)) & ~(1 << (j-1)),  s[r^1] | (1 <<(i-1)) | (1 <<(j-1)), r^1, i*10+j);
                    vis[s[r] & ~(1 <<(i-1)) & ~(1 << (j-1))][ s[r^1] | (1 <<(i-1)) | (1 <<(j-1))][r^1] = 0;
                    // cout<<endl;
                } 
                else if(r == 1){
                    if( vis[s[r^1] | (1 <<(i-1)) | (1 <<(j-1))][ s[r] & ~(1 <<(i-1)) & ~(1 << (j-1))][r^1] == 1) continue;
                    vis[s[r^1] | (1 <<(i-1)) | (1 <<(j-1))][ s[r] & ~(1 <<(i-1)) & ~(1 << (j-1))][r^1] = 1;
                    if(peo == i*10+j) continue;
                    rid[t+1] = r;
                    bk[t+1][1] = i, bk[t+1][2] = j;
                    dfs(t+1, s[r^1] | (1 <<(i-1)) | (1 <<(j-1)),  s[r] & ~(1 <<(i-1)) & ~(1 << (j-1)),  r^1 , i*10+j);
                    vis[s[r^1] | (1 <<(i-1)) | (1 <<(j-1))][ s[r] & ~(1 <<(i-1)) & ~(1 << (j-1))][r^1] = 0;
                }        
            }
        }
    }
}
int main(){
    // cout<<"zhuangtai: "<<chk(63)<<endl;
    dfs(0,255,0,0,0);
    // cout<<ans<<endl;
    for(int i = 1; i <= ans; i++){
        if(id[i] == 0)
            cout<<"qu: "<<lg[i][1]<<" "<<lg[i][2]<<endl;
        else
            cout<<"hui: "<<lb[i][1]<<" "<<lb[i][2]<<endl;
    }
    cout<<ans<<endl;
    return 0;
}

/*
  8 7 6 5 4 3 2 1
  c p f m b b g g
  1 1 1 1 1 1 1 1
  
警察和犯人过河警察回来
犯人

警察女孩1过河警察犯人回来
女孩1

女人女孩2过河女人回来
女孩1、女孩2

女人男人过河男人回来
女人、女孩1、女孩2

警察犯人过河女人回来
警察、犯人、女孩1、女孩2

女人男人过河男人回来
女人、警察、犯人、女孩1、女孩2

男人男孩1过河警察犯人回来
女人、男人、女孩1、女孩2、男孩1

警察男孩2过河警察回来
女人、男人、女孩1、女孩2、男孩1、男孩2

警察犯人过河(通关)
女人、男人、女孩1、女孩2、男孩1、男孩2、警察、犯人
*/


建立前后阶段的关系-path数组,然后用图论、DP思维构建代码(本题bfs)
#include<bitsstdc++.h>
using namespace std;
int dp[1<<8][1<<8][2], k=1, b[] = {0, 0, 0, 0, 0, 1, 1, 1, 0}, pre,t=0;
void print(int x){
    int s[15], t = 0;
    memset(s, 0, sizeof s);
    while(x){
        s[++t] = (x&1);
        x >>= 1;
    }
    for(int i = 8; i >= 1; i--)
        cout<<s[i];
    cout<<" ";
}
int chk(int ls){
            // if(ls & 11000000 == 10000000) if(ls & 00111111 > 0) 犯人在警察不在且还有其他人
    if((ls & 192) == 128 && (ls & 63) > 0) return 0; 
           // if(ls & 110011  -  100011) //爸爸在妈妈不在,女儿在
    if((ls & 51) >= 33 && (ls & 51) <= 35) return 0;
            // if(ls & 111100 > 011100)//妈妈在爸爸不在,儿子在
    if((ls & 60) == 28 || (ls & 60) == 24 || (ls & 60) == 20) return 0;
    return 1;
}
void get_path(){
    for(int u = (1<<8)-1; u; u--){//256 没有顺序的~,没有办法直接dp,必须要给一个合理的转移
        for(int v = 0; v <= (1<<8)-1; v++){//256
                if(u&v != 0 || u|v != 255) continue;//两边
            
                   
                    for(int i = 1; i < 8; i++){//8
                        for(int j = i+1; j <= 8; j++){//8
                           
                            if(!b[i] && !b[j]) continue;  
                            if((u&(1<<(i-1))) == 0 || (u&(1<<(j-1))) == 0) continue;
                            int p = u^(1<<(i-1))^(1<<(j-1)), q = v|(1<<(i-1)|1<<(j-1));
                            if(chk(p) && chk(q)){
                                // dp[p][q][1] = min( dp[p][q][1], dp[u][v][0] + 1); 
                                path[++t][0].l = u;
                                path[t][0].r = v;
                                path[t][0].k = 0;
                                path[t][1].l = p;
                                path[t][1].r = q;  
                                path[t][1].k = 1;


                                path[u<<8|(v<<1)|0][b[u<<8|(v<<1)|0]++] = (p<<9)|(q<<1)|1;

                                // if(t > 5) return 0;  
                                // print(u); print(v);    cout<<endl;
                                // print(p); print(q);    cout<<endl; 
                                // cout<<endl;                  
                            }  
                        }
                    }
                
                
                    for(int i = 1; i <= 8; i++){
                        if(!b[i]) continue;
                        if((v & (1<<(i-1))) == 0) continue;
                        int p = u|1<<(i-1), q = v^(1<<(i-1));
                        if(chk(p) && chk(q)){
                            path[++t][0].l = u;
                            path[t][0].r = v;
                            path[t][0].k = 1;
                            path[t][1].l = p;
                            path[t][1].r = q;
                            path[t][1].k = 0;

                            path[u<<8|(v<<1)|1][b[u<<8|(v<<1)|1]++] = (p<<9)|(q<<1)|0;
                            
                        }
                    }
                    for(int i = 1; i <= 8; i++){
                        for(int j = 1; j <= 8; j++){
                            if(!b[i] && !b[j]) continue;
                            if((v & (1<<(i-1))) == 0 || (v & (1<<(j-1))) == 0) continue;
                            int p = u|(1 <<(i-1)|1<<(j-1)), q = v^(1<<(i-1))^(1<<(j-1));
                            if(chk(p) && chk(q)){
                                path[++t][0].l = u;
                                path[t][0].r = v;
                                path[t][0].k = 1;
                                path[t][1].l = p;
                                path[t][1].r = q;
                                path[t][1].k = 0;

                                path[u<<8|(v<<1)|1][b[u<<8|(v<<1)|1]++] = (p<<9)|(q<<1)|0;
                                
                            }
                        }
                    }
                      
            }
        }
}
int main(){
    memset(dp, 0x3f, sizeof dp);
    dp[255][0][0] = 0;

    bfs();

    cout<<dp[0][255][1]<<endl;
    return 0;
}

3.骨牌
https://blog.csdn.net/Since_natural_ran/article/details/77873027

#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>

using namespace std;

const int maxn = 15;

int n,m,w;
long long dp[maxn][1<<maxn];
int path[5000000][2];

void get_path()
{
    for(int i = 0;i < (1<<m); i++) {
        for(int j = 0;j < (1<<m); j++) {
            int ok = true;
            for(int k = 0;k < m; k++)
            if(ok) {
                if((i&(1<<k)) == 0) {
                    if((j&(1<<k)) == 0) {
                        ok = false;
                        break;
                    }
                }
                else {
                    if((j&(1<<k)) == 0) continue;
                    k++;
                    if(k >= m || (i&(1<<k)) == 0) {
                        ok =  false;
                        break;
                    }
                    else {
                        if((j&(1<<(k-1))) && (j&(1<<k)) == 0) {
                            ok = false;
                            break;
                        }
                        else if((j&(1<<(k-1))) == 0 && (j&(1<<k))) {
                            k--;
                        }
                    }
                }
            }
            if(ok) {
                path[w][0] = i;
                path[w++][1] = j;
            }
        }
    }
}

int main()
{
    //freopen("in.txt","r",stdin);

    while(scanf("%d%d",&n,&m) != EOF) {
        if(n+m == 0) break;
        if(n<m) swap(n,m);
        w = 0;
        get_path();
        memset(dp,0,sizeof(dp));
        dp[0][(1<<m)-1] = 1;
        for(int i = 0;i < n; i++) {
            for(int j = 0;j < w; j++) {
                dp[i+1][path[j][1]] += dp[i][path[j][0]];
            }
        }
        printf("%I64d\n",dp[n][(1<<m)-1]);
    }

    return 0;
}
#include <iostream>
#include <cstring>
#include <cstdio>
#include <algorithm>

using namespace std;

const int maxn = 15;

int n,m,w;
int path[500000][2];
long long dp[maxn][1<<maxn];

void dfs(int pre,int now,int c)
{
    if(c > m) return ;
    if(c == m) {
        path[w][0] = pre;
        path[w++][1] = now;
        return ;
    }
    dfs((pre<<1)|1,now<<1,c+1);
    dfs(pre<<1,(now<<1)|1,c+1);
    dfs((pre<<2)|3,(now<<2)|3,c+2);
}

int main()
{
//    freopen("in.txt","r",stdin);

    while(scanf("%d%d",&n,&m) != EOF) {
        if(n+m==0) break;
        if(m>n) swap(n,m);
        w = 0;
        dfs(0,0,0);
        memset(dp,0,sizeof(dp));
        dp[0][(1<<m)-1] = 1;
        for(int i = 0;i < n; i++) {
            for(int j = 0;j < w; j++) {
                dp[i+1][path[j][1]] += dp[i][path[j][0]];
            }
        }
        printf("%lld\n",dp[n][(1<<m)-1]);
    }

    return 0;
}

三色括号序列
简化问题,没有问题,任意选一种颜色,它是合法的
( ( ) ( ) )
蓝绿红红绿蓝
红色,是不合法的,因此上述染色方法不行

#include <bits/stdc++.h>
#define mod 998244353
#define ll long long
using namespace std;
int n;
inline void add(int &x, int y) { x = (x + y) % mod; }
int dp[2][155][155][155];
string s;
int main() {
    cin >> n;
    cin >> s;
    s = ' ' + s;
    dp[0][0][0][0] = 1;
    for (int i = 0; i < n; i++)
        for (int a = 0; a <= min(i, n - i); a++)
            for (int b = 0; b <= min(i, n - i); b++)
                for (int c = 0; c <= min(i, n - i) && a + b + c <= n + n - i - i; c++) {
                    if (s[i + 1] != ')') {
                        add(dp[(i + 1) % 2][a + 1][b + 1][c], dp[i % 2][a][b][c]);
                        add(dp[(i + 1) % 2][a][b + 1][c + 1], dp[i % 2][a][b][c]);
                        add(dp[(i + 1) % 2][a + 1][b][c + 1], dp[i % 2][a][b][c]);
                    }
                    if (s[i + 1] != '(') {
                        if (a && b)
                            add(dp[(i + 1) % 2][a - 1][b - 1][c], dp[i % 2][a][b][c]);
                        if (b && c)
                            add(dp[(i + 1) % 2][a][b - 1][c - 1], dp[i % 2][a][b][c]);
                        if (a && c)
                            add(dp[(i + 1) % 2][a - 1][b][c - 1], dp[i % 2][a][b][c]);
                    }
                    dp[i % 2][a][b][c] = 0;  //因为累加 += ,所以即将更新的这一步要清零
                }
    cout << dp[n % 2][0][0][0];
    cout << endl;
}

#include<bitsstdc++.h>
#define mod 998244353
#define ll long long
using namespace std;
int n;
inline void add(int &x,int y) {x=(x+y)%mod;}
int dp[105][55][55][55],tot;
string s;
int main(){
	cin>>n; 
    // cin>>s;
    // s = ' '+s;
	// dp[0][0][0][0]=1;
    for (int i=0;i<n;i++)
       for (int a=0;a<=min(i,n-i);a++)
		    for (int b=0;b<=min(i,n-i);b++)
		         for (int c=0;c<=min(i,n-i);c++){
                   if((a+b+c)%2 == 1) continue;
                   if((a+b+c+1)/2 > n-i) continue;
                   if(max(a,max(b,c)) - min(a,min(b,c)) > n-i) continue;
                   tot++;
                }
    cout<<tot<<endl;
}
/*
22
?(??????????????(?????
550426020

44
?????????(?????????????(??????(?????????????

50
???????????(?????????????????????????????(????????
855923589

46
(????(????????(?)???((????))????????(???????))
251335850

50
??????(??????????????????????????????????????????? 
272659952
*/

posted on 2025-03-20 16:44  Jeanny  阅读(18)  评论(0)    收藏  举报