这里会显示出您选择的修订版和当前版本之间的差别。
| 后一修订版 | 前一修订版 | ||
|
2020-2021:teams:wangzai_milk:weekly:poj_2411 [2020/05/09 12:06] zars19 创建 |
2020-2021:teams:wangzai_milk:weekly:poj_2411 [2020/05/10 01:33] (当前版本) zars19 ↷ 页面2020-2021:teams:wangzai_milk:poj_2411被移动至2020-2021:teams:wangzai_milk:weekly:poj_2411 |
||
|---|---|---|---|
| 行 1: | 行 1: | ||
| [[http://poj.org/problem?id=2411|POJ 2411]] | [[http://poj.org/problem?id=2411|POJ 2411]] | ||
| - | |||
| - | 有横向运输和纵向运输的两种矿(要送到左端/上方),每个格子只能建一种方向(横/纵)的管道,最大化送到的矿的价值。 | ||
| - | |||
| - | **题解**:想象一下对于每一格子来说如果它建横向那它左边必然都是横向才有意义,纵向同理。搞一下前缀和,状态转移<code cpp>dp[i][j]=max(dp[i-1][j]+prea[i][j]-prea[i-1][j],dp[i][j-1]+preb[i][j]-preb[i][j-1])</code> | ||
| <code cpp> | <code cpp> | ||
| 行 12: | 行 8: | ||
| #include<cstdlib> | #include<cstdlib> | ||
| using namespace std; | using namespace std; | ||
| - | int n,m,dp[505][505],prea[505][505],preb[505][505]; | + | int h,w; |
| + | long long f[12][(1<<12)]; | ||
| + | int read() | ||
| + | { | ||
| + | int x=0,f=1;char c=getchar(); | ||
| + | while(c<'0'||c>'9'){if(c=='-')f=-1;c=getchar();} | ||
| + | while(c>='0'&&c<='9'){x=x*10+c-'0';c=getchar();} | ||
| + | return x*f; | ||
| + | } | ||
| int main() | int main() | ||
| { | { | ||
| - | while(~scanf("%d%d",&n,&m)) | + | h=read(),w=read(); |
| + | while(h&&w) | ||
| { | { | ||
| - | if(!n&&!m)return 0; | + | if((h*w)%2){puts("0"),h=read(),w=read();continue;} |
| - | for(int i=1;i<=n;i++) | + | memset(f,0,sizeof(f)); |
| - | for(int j=1;j<=m;j++) | + | if(!h&&!w)break; |
| - | { | + | for(int i=1;i<=h;i++) |
| - | scanf("%d",&prea[i][j]); | + | |
| - | prea[i][j]+=prea[i][j-1]+prea[i-1][j]-prea[i-1][j-1]; | + | |
| - | } | + | |
| - | for(int i=1;i<=n;i++) | + | |
| - | for(int j=1;j<=m;j++) | + | |
| - | { | + | |
| - | scanf("%d",&preb[i][j]); | + | |
| - | preb[i][j]+=preb[i][j-1]+preb[i-1][j]-preb[i-1][j-1]; | + | |
| - | } | + | |
| - | for(int i=1;i<=n;i++) | + | |
| - | for(int j=1;j<=m;j++) | + | |
| { | { | ||
| - | dp[i][j]=max(dp[i-1][j]+prea[i][j]-prea[i-1][j],dp[i][j-1]+preb[i][j]-preb[i][j-1]); | + | for(int j=0;j<(1<<w);j++) |
| + | { | ||
| + | if(i==1) | ||
| + | { | ||
| + | f[i][j]=1; | ||
| + | for(int l=1;l<(1<<w);l<<=1) | ||
| + | { | ||
| + | if((j&l)==0) | ||
| + | { | ||
| + | if((l<<1)>=(1<<w)){f[i][j]=0;break;} | ||
| + | else if(j&(l<<1)){f[i][j]=0;break;} | ||
| + | else l<<=1; | ||
| + | } | ||
| + | } | ||
| + | } | ||
| + | else | ||
| + | { | ||
| + | for(int k=0;k<(1<<w);k++) | ||
| + | { | ||
| + | if(!f[i-1][k])continue; | ||
| + | f[i][j]+=f[i-1][k]; | ||
| + | for(int l=1;l<(1<<w);l<<=1) | ||
| + | { | ||
| + | if(k&l) | ||
| + | { | ||
| + | if(j&l){f[i][j]-=f[i-1][k];break;} | ||
| + | } | ||
| + | else if((j&l)==0) | ||
| + | { | ||
| + | if((l<<1)>=(1<<w)){f[i][j]-=f[i-1][k];break;} | ||
| + | else if(j&(l<<1)){f[i][j]-=f[i-1][k];break;} | ||
| + | else if(k&(l<<1)){f[i][j]-=f[i-1][k];break;} | ||
| + | else l<<=1; | ||
| + | } | ||
| + | } | ||
| + | } | ||
| + | } | ||
| + | } | ||
| } | } | ||
| - | printf("%d\n",dp[n][m]); | + | printf("%lld\n",f[h][0]); |
| + | h=read(),w=read(); | ||
| } | } | ||
| return 0; | return 0; | ||
| } | } | ||
| </code> | </code> | ||