【Uva 10118】Free Candies

Link:

Description

有4堆书;
每本书编号从1..20
每堆书都是N本;
然后每次只能从任意一堆的堆顶拿一本书装到自己的口袋里;
你的口袋最多容纳5本书;
当你的口袋里有两本一样的书的时候,那一对书就归你了;
但是一旦你的口袋装满了,就不能再装书了;游戏停止
问你最多能拿多少对书。

Solution

比较明显的动规了;
每次只能从4堆书的堆顶中选择一本书
定义f[i][j][k][l]表示第一堆书上有i本数,第二堆书。。。。获得的最大书对数;
则从某一堆书上拿一本书;
相当于某一维变量的值减去1;
写个前缀和,记录最初始每一堆书的第j本书上面1..20这些书各有多少本
转移的时候,就能根据这个前缀和,获取之前拿了哪些书了;
成对的消掉,增加数目,不能成对的,则记录书的类型;
对于拿的书的类型<5的状态做转移就好;

NumberOf WA

0

Reviw


Code

#include <bits/stdc++.h>
using namespace std;

const int N = 40;
const int INF = 0x3f3f3f3f;

int n,x[5][N+10],f[N+5][N+5][N+5][N+5],pre[5][N+10][21];
int temp[22];

pair<int,int> tongji(int a,int b,int c,int d){
    memset(temp,0,sizeof temp);
    for (int i = 1;i <= 20;i++){
        temp[i] += pre[1][a][i];
        temp[i] += pre[2][b][i];
        temp[i] += pre[3][c][i];
        temp[i] += pre[4][d][i];
    }
    int num = 0,num1 = 0;
    for (int i = 1;i <= 20;i++){
        num+=temp[i]/2;
        temp[i]%=2;
        num1+=temp[i];
    }
    return make_pair(num1,num);
}

int main(){
    //freopen("F:\rush.txt","r",stdin);
    while (~scanf("%d",&n) && n){
        for (int i = n;i >= 1;i--)
            for (int j = 1;j <= 4;j++)
                scanf("%d",&x[j][i]);

        for (int i = 1;i <= 4;i++){
            for (int k = 1;k <= 20;k++) pre[i][n+1][k] = 0;
            for (int j = n;j >= 1;j--){
                for (int k = 1;k <= 20;k++)
                    pre[i][j][k] = pre[i][j+1][k];
                pre[i][j][x[i][j]]++;
            }
        }

        memset(f,-INF,sizeof f);
        f[n][n][n][n] = 0;
        int ans = 0;
        pair <int,int> pii;
        for (int i = n;i >= 0;i--)
            for (int j = n;j >= 0;j--)
                for (int k = n;k >= 0;k--)
                    for (int l = n;l >= 0;l--)
                        if (f[i][j][k][l]>=0){
                            ans = max(ans,f[i][j][k][l]);
                            if (i){
                                pii = tongji(i,j+1,k+1,l+1);
                                if (pii.first<5){
                                    int &t = f[i-1][j][k][l];
                                    t = max(t,pii.second);
                                }
                            }
                            if (j){
                                pii = tongji(i+1,j,k+1,l+1);
                                if (pii.first<5){
                                    int &t = f[i][j-1][k][l];
                                    t = max(t,pii.second);
                                }
                            }
                            if (k){
                                pii = tongji(i+1,j+1,k,l+1);
                                if (pii.first<5){
                                    int &t = f[i][j][k-1][l];
                                    t = max(t,pii.second);
                                }
                            }
                            if (l){
                                pii = tongji(i+1,j+1,k+1,l);
                                if (pii.first<5){
                                    int &t = f[i][j][k][l-1];
                                    t = max(t,pii.second);
                                }
                            }
                        }
        printf("%d
",ans);
    }
    return 0;
}
原文地址:https://www.cnblogs.com/AWCXV/p/7626175.html