過河
#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
警察犯人過河(通關(guān))
女人、男人、女孩1、女孩2、男孩1、男孩2、警察、犯人
*/
建立前后階段的關(guān)系-path數(shù)組,然后用圖論、DP思維構(gòu)建代碼(本題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,必須要給一個合理的轉(zhuǎn)移
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;
}
三色括號序列
簡化問題,沒有問題,任意選一種顏色,它是合法的
( ( ) ( ) )
藍(lán)綠紅紅綠藍(lán)
紅色,是不合法的,因此上述染色方法不行
#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
*/
浙公網(wǎng)安備 33010602011771號