Luogu 2668 【NOIP2015】斗地主

打牌技术不精,没有把$A$放在顺子里面搜,WA了好长时间。

盗用大佬的一张图:

当时自己搜的时候没有把四张牌拆成三带一等情况。

然后还有一点就是四张三张都出完之后直接数一数剩下的一张两张牌还要多少次出完就好了,没有必要浪费栈空间和递归深度去搜这些东西。(我就是这样T了好多次QωQ)。

要注意暴力算的前提就是一定要把之前的三张四张打完。

玄学复杂度。

代码很丑很长。

Code:

#include <cstdio>
#include <cstring>
using namespace std;

const int N = 20;
const int inf = 1 << 30;

int testCase, n, cnt[N], ans;

inline void read(int &X) {
    X = 0; char ch = 0; int op = 1;
    for(; ch > '9' || ch < '0'; ch = getchar())
        if(ch == '-') op = -1;
    for(; ch >= '0' && ch <= '9'; ch = getchar())
        X = (X << 3) + (X << 1) + ch - 48;
    X *= op;
}

inline void chkMin(int &x, int y) {
    if(y < x) x = y;
}

void dfs(int rest, int stp) {    
    if(stp >= ans) return;
    if(rest == 0) {
        chkMin(ans, stp);
        return;
    }
    
/*    for(int j, i = 3; i <= 14; i++) {
        if(cnt[i] < 1) continue; 
        for(j = i; j <= 14; j++)
            if(cnt[j] < 1) break;
        j--;
        if(j - i + 1 < 5) {
            i = j;
            continue;
        }
        for(int k = i; k <= j; k++) --cnt[k];
        dfs(rest - (j - i + 1), stp + 1);
        for(int k = i; k <= j; k++) ++cnt[k];
        i = j;
    }    
    
    for(int j, i = 3; i <= 14; i++) {
        if(cnt[i] < 2) continue; 
        for(j = i; j <= 14; j++)
            if(cnt[j] < 2) break;
        j--;
        if(j - i + 1 < 3) {
            i = j;
            continue;
        }
        for(int k = i; k <= j; k++) cnt[k] -= 2;
        dfs(rest - (j - i + 1) * 2, stp + 1);
        for(int k = i; k <= j; k++) cnt[k] += 2;
        i = j;
    }
    
    for(int j, i = 3; i <= 14; i++) {
        if(cnt[i] < 3) continue; 
        for(j = i; j <= 14; j++)
            if(cnt[j] < 3) break;
        j--;
        if(j - i + 1 < 2) {
            i = j;
            continue;
        }
        for(int k = i; k <= j; k++) cnt[k] -= 3;
        dfs(rest - (j - i + 1) * 3, stp + 1);
        for(int k = i; k <= j; k++) cnt[k] += 3;
        i = j;
    }  */

/*    for(int j, k, i = 2; i <= 14; i++) {
        if(cnt[i] < 4) continue;
        for(j = 2; j <= 15; j++) {
            if(j == i) continue;
            if(cnt[j] > 1) {
                for(k = 2; k <= 15; k++) {
                    if(k == i) continue;
                    if(cnt[k] > 1) {
                        cnt[i] -= 4, cnt[j] -= 2, cnt[k] -= 2;
                        dfs(rest - 8, stp + 1);
                        cnt[i] += 4, cnt[j] += 2, cnt[k] += 2;
                    }
                }
            }
        }
    }

    for(int j, k, i = 2; i <= 14; i++) {
        if(cnt[i] < 4) continue;
        for(j = 2; j <= 15; j++) {
            if(j == i) continue;
            if(cnt[j] > 0) {
                for(k = 2; k <= 15; k++) {
                    if(k == i) continue;
                    if(cnt[k] > 0) {
                        cnt[i] -= 4, --cnt[j], --cnt[k];
                        dfs(rest - 6, stp + 1);
                        cnt[i] += 4, ++cnt[j], ++cnt[k];
                    }
                }
            }
        }
    }

    for(int i = 2; i <= 14; i++) {
        if(cnt[i] < 4) continue;
        cnt[i] -= 4;
        dfs(rest - 4, stp + 1);
        cnt[i] += 4;
    }

    for(int j, i = 2; i <= 14; i++) {
        if(cnt[i] < 3) continue;
        for(j = 2; j <= 15; j++) {
            if(j == i) continue;
            if(cnt[j] > 1) {
                cnt[i] -= 3, cnt[j] -= 2;
                dfs(rest - 5, stp + 1);
                cnt[i] += 3, cnt[j] += 2;   
            }
        }
    }

    for(int j, i = 2; i <= 14; i++) {
        if(cnt[i] < 3) continue;
        for(j = 2; j <= 15; j++) {
            if(j == i) continue;
            if(cnt[j] > 0) {
                cnt[i] -= 3, --cnt[j];
                dfs(rest - 4, stp + 1);
                cnt[i] += 3, ++cnt[j];  
            }
        }       
    }

    for(int i = 2; i <= 14; i++) {
        if(cnt[i] < 3) continue;
        cnt[i] -= 3;
        dfs(rest - 3, stp + 1);
        cnt[i] += 3;
    }   */
    
    int len = 0;
    for(int i = 3; i <= 14; i++) {
        if(cnt[i] == 0) len = 0;
        else {
            ++len;
            if(len >= 5) {
                for(int j = i; j >= i - len + 1; j--) cnt[j]--;
                dfs(rest - len, stp + 1);
                for(int j = i; j >= i - len + 1; j--) cnt[j]++;
            }
        }
    }
    
    len = 0;
    for(int i = 3; i <= 14; i++) {
        if(cnt[i] <= 1) len = 0;
        else {
            ++len;
            if(len >= 3) {
                for(int j = i; j >= i - len + 1; j--) cnt[j] -= 2;
                dfs(rest - len * 2, stp + 1);
                for(int j = i; j >= i - len + 1; j--) cnt[j] += 2; 
            }
        }
    }
    
    len = 0;
    for(int i = 3; i <= 14; i++) {
        if(cnt[i] <= 2) len = 0;
        else {
            len++;
            if(len >= 2) {
                for(int j = i; j >= i - len + 1; j--) cnt[j] -= 3;
                dfs(rest - len * 3, stp + 1);
                for(int j = i; j >= i - len + 1; j--) cnt[j] += 3;
            }
        }
    }
    
    for(int i = 2; i <= 14; i++) {
        if(cnt[i] <= 3) {
            if(cnt[i] <= 2) continue;
            cnt[i] -= 3;
            for(int j = 2; j <= 15; j++) {
                if(j == i || cnt[j] == 0) continue;
                cnt[j]--;
                dfs(rest - 4, stp + 1);
                cnt[j]++;
            }
            for(int j = 2; j <= 15; j++) {
                if(j == i || cnt[j] <= 1) continue;
                cnt[j] -= 2;
                dfs(rest - 5, stp + 1);
                cnt[j] += 2;
            }
            cnt[i] += 3;
        } else {
            cnt[i] -= 3;
            for(int j = 2; j <= 15; j++) {
                if(j == i || cnt[j] == 0) continue;
                cnt[j]--;
                dfs(rest - 4, stp + 1);
                cnt[j]++;
            }
            for(int j = 2; j <= 15; j++) {
                if(j == i || cnt[j] <= 1) continue;
                cnt[j] -= 2;
                dfs(rest - 5, stp + 1);
                cnt[j] += 2;
            }
            cnt[i] += 3;
            
            cnt[i] -= 4;
            for(int j = 2; j <= 15; j++) {
                if(j == i || cnt[j] == 0) continue;
                cnt[j]--;
                for(int k = 2; k <= 15; k++) {
                    if(k == j || cnt[k] == 0) continue;
                    cnt[k]--;
                    dfs(rest - 6, stp + 1);
                    cnt[k]++;
                }
                cnt[j]++;
            }
            
            for(int j = 2; j <= 14; j++) {
                if(j == i || cnt[j] <= 1) continue;
                cnt[j] -= 2;
                for(int k = 2; k <= 14; k++) {
                    if(k == j || cnt[k] <= 1) continue;
                    cnt[k] -= 2;
                    dfs(rest - 8, stp + 1);
                    cnt[k] += 2;
                }
                cnt[j] += 2;
            }
            cnt[i] += 4;
        }
    }
    
    int now = 0;
    for(int i = 2; i <= 15; i++)
        if(cnt[i]) ++now;
    
    chkMin(ans, stp + now);
}

int main() {
//    freopen("Sample.txt", "r", stdin);
//    freopen("testdata.in", "r", stdin);
//    freopen("my.txt", "w", stdout);

    read(testCase), read(n);
    for(; testCase--; ) {
        memset(cnt, 0, sizeof(cnt));

        for(int x, y, i = 1; i <= n; i++) {
            read(x), read(y);
            if(x == 0) cnt[15]++; 
            else {
                if(x == 1) cnt[14]++;
                else cnt[x]++;
            }
        }

        ans = inf;
        dfs(n, 0);

        printf("%d\n", ans);
    }
    return 0;
}
View Code

猜你喜欢

转载自www.cnblogs.com/CzxingcHen/p/9667834.html
今日推荐