zoj-3802-Easy 2048 Again

来源:互联网 发布:如何保存淘宝视频 编辑:程序博客网 时间:2024/06/08 07:54

简单的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;}


0 0