zoj-3802-Easy 2048 Again

简单的dp。

dp[i][j]:在第i位置,递减的状态为j,所获得的最大利润。

枚举状态,如果加进来的数x比状态的最小的要大,那么直接状态变为x。

如果x比最小的要小,那么状态为j+x。

如果x等于最小的,那么依次加和,直至最小的比x大。

#include <iostream>
#include<stdio.h>
#include<vector>
#include<queue>
#include<stack>
#include<string.h>
#include<algorithm>
#include<math.h>
using namespace std;
int pan(int x)
{
    if(x==2)return 1;
    if(x==4)return 2;
    if(x==8)return 3;
    if(x==16)return 4;
}
int dp[505][1<<13];
int a[550];
queue<int>que;
void chu(int s,int ss,int k,int x)
{
    dp[s][x]=max(dp[s][x],dp[ss][0]+x);
    if(k==0)return;
    if(dp[ss][k]==0)return;
    dp[s][k]=max(dp[s][k],dp[ss][k]);
    while(!que.empty())que.pop();
    int y=x;
    int add=x;
    for(int i=0; i<13; i++)
    {
        int now=(1<<i);
        if((k&now)==0)continue;
        if(now<y)dp[s][x]=max(dp[s][x],dp[ss][k]+x);
        if(now>y)dp[s][k+x]=max(dp[s][k+x],dp[ss][k]+add);
        if(now!=y)return;
        y=y*2;
        add+=y;
    }
    dp[s][y]=max(dp[s][y],dp[ss][k]+add);
}
int main()
{
    int T,n;
    scanf("%d",&T);
    while(T--)
    {
        scanf("%d",&n);
        int sum=0;
        for(int i=1; i<=n; i++)
        {
            scanf("%d",&a[i]);
            sum+=a[i];
        }
        for(int i=1; i<=n; i++)
        {
            for(int j=0; j<=sum; j++)dp[i][j]=0;
        }
        for(int i=1; i<=n; i++)
        {
            for(int j=0; j<=sum; j++)
            {
                chu(i,i-1,j,a[i]);
            }
        }
        int maxx=0;
        for(int i=0; i<=sum; i++)maxx=max(maxx,dp[n][i]);
        cout<<maxx<<endl;
    }
    return 0;
}
时间: 2024-11-12 10:56:39

zoj-3802-Easy 2048 Again的相关文章

ZOJ 3802 Easy 2048 Again 状压DP

直接从前往后DP,因为一共只有500个数,所以累加起来的话单个数不会超过4096,并且因为是Flappy 2048的规则,所以只有之后数列末尾一串递减的是有效的,因此可以状压. 1700ms = =,据说用滚动数组优化一下会好很多 #include <cstdio> #include <cstring> #include <iostream> #include <map> #include <set> #include <vector>

ZOJ 3802 Easy 2048 Again 状态DP

zoj 上次的月赛题,相当牛的题目啊,根本想不到是状态压缩好吧 有个预先要知道的,即500个16相加那也是不会超过8192,即,合并最多合并到4096,只有2的12次方 所以用状态压缩表示前面有的序列组合,找到了符合的,就往上累加合并生成新状态,否则就添加到前面的状态的后面构成新状态,因为每一个的状态都由前一个所得,用滚动数组即可 #include <iostream> #include <cstdio> #include <cstring> #include <

ZOJ 3802 Easy 2048 Again ( 状态压缩 )

题目链接~~> 做题感悟:这题很经典 ,需要模拟一下找规律,还是那句话遇到题自己应该手动推一下. 解题思路: 这题如果手动推几组数据的话就应该发现 ,如果放进队列的元素是递减的话,这样才可以连续合并,如果队列中有 a  ,b , a < b 那么 a 前面的必定不会与 b 经过合并再合并,因为越合并越大,so ~> 队列中最多才存 12 个数,可以用状态压缩压缩一下.注意要用滚动数组,不用可能超时. 代码: #include<iostream> #include<sst

Easy 2048 Again - ZOJ 3802 像缩进dp

Easy 2048 Again Time Limit: 2 Seconds      Memory Limit: 65536 KB Dark_sun knows that on a single-track road (which means once he passed this area, he cannot come back again), there are some underground treasures on each area of the road which has th

ZOJ3802 Easy 2048 Again (状压DP)

ZOJ Monthly, August 2014 E题 ZOJ月赛 2014年8月 E题 http://acm.zju.edu.cn/onlinejudge/showProblem.do?problemId=5334 Easy 2048 Again Time Limit: 2 Seconds      Memory Limit: 65536 KB Dark_sun knows that on a single-track road (which means once he passed this

ZOJ 2969: Easy Task

ZOJ 2969: Easy Task 1 ///@date 2017-02-07 2 ///@author Sycamore, ZJNU 3 #include <iostream> 4 using namespace std; 5 int c[1001]; 6 int main() 7 { 8 int T; 9 cin >> T; 10 while (T--) 11 { 12 int N; 13 cin >> N; 14 for (int i = N; i >=

[ACM] ZOJ 3844 Easy Task (模拟+哈希)

Easy Task Time Limit: 2 Seconds      Memory Limit: 65536 KB You are given n integers. Your task is very easy. You should find the maximum integer a and the minimum integer b among these n integers. And then you should replace both a and bwith a-b. Yo

Easy 2048 Again(状压dp)

题目链接:http://acm.zju.edu.cn/onlinejudge/showProblem.do?problemCode=3802 题意: 从数列A中, 删除若干个数(可以0个), 是删除后的数列, 进行类似  Flappy 2048 游戏的运算, 使结果最大, 求该最大值. 题解: 每个数ai, 取或不取, 满足 可用二进制表示. 当 ai < a[i + 1] 是, 易想到 如果两个数都取, ai 将不会在合并. 所以只需考虑ai[i + 1] 前的 降序列即可 .如果没个数都为1

zoj3802:easy 2048 again(状压dp)

zoj月赛的题目,非常不错的一个状压dp.. 题目大意是一个一维的2048游戏 只要有相邻的相同就会合并,合并之后会有奖励分数,总共n个,每个都可以取或者不取 问最终得到的最大值 数据范围n<=500 , a[i]={2,4,8,16}: 分析: 首先明确一下自动合并的意思,比如原有 8,4,2,进入一个2 就会变成16 所以我们需要记录前面的所有数字..计算了一下发现最大情况,500个16会合成4096 =2^12 显然全部记录是不可能的.那么怎么处理呢 我们发现,只有递减的序列才有可能向前合

ZOJ 3761 Easy billiards (DFS性质)

题意  桌上有n个球  a球撞击b球时  a球停在b球位置  b球保持a球运动   若b球前面再没有球  b球就会掉下桌子  给你n个球的坐标  你可以多次选择某个撞击方向前面还有球的球撞击  问最后桌上至少还剩多少球  并输出你的撞击过程 可以把x坐标或y坐标相同的点当作是连通的 因为可以通过撞击一个球使另一个球掉下桌面 那么容易发现  一个连通块内的m个球总可以经过m-1次撞击后变成只剩一个球  这个球可以是当前连通块中的任意一个  有多少个连通块最后就最少剩下多少球  然后就可以通过一次d