• 【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;
    }
  • 相关阅读:
    stack的基本使用方式
    洛谷 P2356 弹珠游戏
    关于字符串数组的一些操作
    递归分解因数
    筛法求素数模板
    世界顶级精英们的人生哲学!(转)
    Oracle 中重新编译无效的存储过程, 或函数、触发器等对象(转)
    由于没有安装音量控制程序,WINDOWS无法在任务栏上显示音量控制(转)
    Maximo(转)
    oracle 中nvl和sql server中isnull功能一样的
  • 原文地址:https://www.cnblogs.com/AWCXV/p/7626175.html
Copyright © 2020-2023  润新知