zoukankan      html  css  js  c++  java
  • Shooting Bricks题解

    题目传送门
    以后我绝对不会一直磕着一道题磕几个小时了...感觉还是自己节奏出了问题,不知为啥感觉有点小慌...
    算了,其实再回头仔细看一下这个题dp的思路还是比较好想出来的,打代码之前一定要做好足够的思想工作,不然之后一定会吃大亏的。
    考虑每一列,其实给定我们只需要知道这一列用了多少子弹即可,用了多少子弹就能知道他能得到的最大值。其次有点细节的就是是不是终点,怎么说呢,若不是终点,则一个N点之后的Y我们都能白嫖,但是终点的话,我们只能打到N就不能继续打了。其次这个列的顺序其实毫无影响,若不是终点的话,我们只需要知道你用了多少子弹就行,你先打谁无所畏惧。那就剩下终点的问题,我们可以枚举每一列作为终点,枚举这一列用到的子弹,再枚举前面所有的列的子弹,就可以算出右边的列用的子弹。许多信息都可以预处理出来。总复杂度为(O(n^3))

    //不等,不问,不犹豫,不回头.
    #include<bits/stdc++.h>
    #define _ 0
    #define ls p<<1
    #define db double
    #define rs p<<1|1
    #define P 1000000007
    #define ll long long
    #define INF 1000000000
    #define get(x) x=read()
    #define PLI pair<ll,int>
    #define PII pair<int,int>
    #define ull unsigned long long
    #define put(x) printf("%d
    ",x)
    #define putl(x) printf("%lld
    ",x)
    #define rep(x,y,z) for(int x=y;x<=z;++x)
    #define fep(x,y,z) for(int x=y;x>=z;--x)
    #define go(x) for(int i=link[x],y=a[i].y;i;y=a[i=a[i].next].y)
    using namespace std;
    const int N=205;
    int fz[N][N],ff[N][N],c[N][N],p[N][N],n,m,k,fre[N][N],frez[N][N];
    char st[N]; 
    
    inline int read()
    {
        int x=0,ff=1;
        char ch=getchar();
        while(!isdigit(ch)) {if(ch=='-') ff=-1;ch=getchar();}
        while(isdigit(ch)) {x=(x<<1)+(x<<3)+(ch^48);ch=getchar();}
        return x*ff;
    }
    
    inline void init()
    {
    	get(n);get(m);get(k);
    	memset(p,0,sizeof(p));
    	memset(fz,0,sizeof(fz));
    	memset(ff,0,sizeof(ff));
    	memset(fre,0,sizeof(fre));
    	memset(frez,0,sizeof(frez));
    	rep(i,1,n) rep(j,1,m)
    	{
    		scanf("%d %s",&c[i][j],st+1);
    		if(st[1]=='Y') p[i][j]=1;
    	}
    }
    
    inline void prework()
    {
    	rep(i,1,m) //统计每一列不同子弹的最多奖金。
    	{
    		int bou=0,ct=0;
    		fep(j,n,1) 
    		{
    			bou+=c[j][i];
    			if(!p[j][i])
    			{
    				ct++;
    				frez[i][ct]=bou;//是终点。 
    			}	
    			fre[i][ct]=bou;//不是终点。 
    		}
    	} 
    	rep(i,1,m) rep(j,0,k) rep(l,0,j)
    		fz[i][j]=max(fz[i][j],fz[i-1][l]+fre[i][j-l]);
    	fep(i,m,1) rep(j,0,k) rep(l,0,j)
    		ff[i][j]=max(ff[i][j],ff[i+1][l]+fre[i][j-l]);
    }
    
    inline void solve()
    {
    	int ans=0; 
    	rep(i,1,m) rep(j,1,k) //枚举终点所在的列和所用的子弹 
    	{
    		rep(l,0,k-j) //枚举左边用的子弹。
    			ans=max(ans,frez[i][j]+fz[i-1][l]+ff[i+1][k-j-l]); 
    	}
    	put(ans);
    }
    
    int main()
    {
        //freopen("1.in","r",stdin);
    	int get(T);
    	while(T--)
    	{
    		init();
    		prework();
    		solve();
    	}
        return (0^_^0);
    }
    //以吾之血,铸吾最后的亡魂.
    
    
  • 相关阅读:
    [笔记] 辛普森积分
    Luogu P4175 [CTSC2008]网络管理
    Luogu P4331 [BOI2004]Sequence 数字序列
    Luogu P1456 Monkey King
    Luogu P3261 [JLOI2015]城池攻占
    Luogu P4309 [TJOI2013]最长上升子序列
    Luogu P4246 [SHOI2008]堵塞的交通
    Luogu P3638 [APIO2013]机器人
    Luogu P4294 [WC2008]游览计划
    CF613D Kingdom and its Cities
  • 原文地址:https://www.cnblogs.com/gcfer/p/15202211.html
Copyright © 2011-2022 走看看