bzoj 1296 DP

6627 단어 ZOJ
매 줄마다 DP 예처리를 하면 w[i][j]는 이 줄 앞에서 i개가 j회 갱신하는 최대 가치를 나타낸다. 그러면 w[i][j]=max(w[i][j], w[k][j]+sum[k+1][i]), sum[i][j]는 i-j단을 한 번에 최대 몇 개까지 갱신한다.
그러면 우리는 각 줄을 하나의 물품으로 간주할 수 있다. 전체적으로 DP를 만들면 W[i][j]는 전 i행이 j회 갱신하는 최대 가치를 나타낸다. 그러면 W[i]=max(W[i][j], W[i-1][j-k]+w[i][k])k반성: k를 열거할 때 방정식을 잘못 썼고 W[i-1][k]+w[i][j-k]로 썼다.
/**************************************************************

    Problem: 1296

    User: BLADEVIL

    Language: C++

    Result: Accepted

    Time:120 ms

    Memory:1564 kb

****************************************************************/

 

//By BLADEVIL

#include <cstdio>

#include <cstring>

#include <algorithm>

#define maxn 60

#define maxk 3000

 

using namespace std;

 

int n,m,t,ans;

int map[maxn][maxn],w[maxn][maxn],sum[maxn][maxn],W[maxn][maxn],ww[maxn][maxk];

char s[maxn];

 

int work(int x) {

    memset(w,0,sizeof w);

    memset(sum,0,sizeof sum);

    for (int i=1;i<=m;i++)

        for (int j=i;j<=m;j++)

            for (int k=i;k<=j;k++)

                if (map[x][k]) sum[i][j]++;

    for (int i=1;i<=m;i++)

        for (int j=i;j<=m;j++) sum[i][j]=max(sum[i][j],j-i+1-sum[i][j]);//printf("%d %d %d
",i,j,sum[i][j]);
    for (int i=1;i<=m;i++)         for (int j=1;j<=m;j++) {             w[j][i]=w[j-1][i];             for (int k=0;k<j;k++)                 w[j][i]=max(w[j][i],w[k][i-1]+sum[k+1][j]);         }     for (int i=1;i<=m;i++) W[x][i]=w[m][i];//printf("%d ",W[x][i]); printf("
");
}   int main() {     scanf("%d %d %d",&n,&m,&t);     for (int i=1;i<=n;i++) {         scanf("%s",s);         for (int j=0;j<m;j++) map[i][j+1]=(s[j]=='1')?1:0;     }     for (int i=1;i<=n;i++) work(i);     for (int i=1;i<=t;i++)         for (int j=1;j<=n;j++)             for (int k=0;k<=min(m,i);k++)                 ww[j][i]=max(ww[j][i],ww[j-1][i-k]+W[j][k]),ans=max(ans,ww[j][i]);     printf("%d
",ans);     return 0; }

좋은 웹페이지 즐겨찾기