BZOJ2310

2310: ParkII

Time Limit: 20 Sec   Memory Limit: 128 MB
Submit: 86   Solved: 34
[ Submit][ Status][ Discuss]

Description

Hnoi2007-Day1有一道题目 Park:给你一个 m * n 的矩阵,每个矩阵内有个
权值V(i,j) (可能为负数),要求找一条回路,使得每个点最多经过一次,并且经过
的点权值之和最大,想必大家印象深刻吧. 
无聊的小 C 同学把这个问题稍微改了一下:要求找一条路径,使得每个点
最多经过一次,并且点权值之和最大,如果你跟小 C 一样无聊,就麻烦做一下
这个题目吧.

Input

第一行 m, n,接下来 m行每行 n 个数即. 
V( i,j)

Output

一个整数表示路径的最大权值之和.

Sample Input

2 3
1 -2 1
1 1 1

Sample Output

5
【数据范围】
30%的数据,n≤6.
100%的数据,m<=100,n ≤ ≤8.
注意:路径上有可能只有一个点.



恶心的杀头DP...
可以看cdq的<基于连通性状态压缩的动态规划问题>
PS:我的代码不知道比mcfx短到哪里去了...


#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<algorithm>
#define maxp 2000000
#define yjq 32767
#define bit(x) ((x)<<1)
using namespace std;
int a[110][10];
int nxt[maxp],head[yjq+10],tot[2],n,m,nn,mm;
int status[2][maxp],ptr,nptr;
int dp[2][maxp],ans=-1<<30;
void add(int x,int s){
    int p=x&yjq;
    for(int t=head[p];t;t=nxt[t])
        if(status[ptr][t]==x){
            dp[ptr][t]=max(dp[ptr][t],s);
            return ;
        }
    tot[ptr]++;
    status[ptr][tot[ptr]]=x;
    dp[ptr][tot[ptr]]=s;
    nxt[tot[ptr]]=head[p],head[p]=tot[ptr];
}
int conn(int x,int j,int k){
    if(k==1){
        int b=1;
        for(int i=j+1;i<=m;++i){
            int p=(x>>bit(i))&3;
            if(p==1)b++;
            else if(p==2)b--;
            if(b==0)return i;
        }
    } else if(k==2){
        int b=1;
        for(int i=j-2;i>=0;--i){
            int p=(x>>bit(i))&3;
            if(p==2)b++;
            else if(p==1)b--;
            if(b==0)return i;
        }
    }
    return -1;
}
bool check0(int x){
//	for(int i=0;i<=m;++i)if(((x>>bit(i))&3)==1)return false;
//	return true;
//	return ()
}
int replace(int x,int j,int to){
	int p=(x>>bit(j))&3;
	return x-(p<<bit(j))+(to<<bit(j));
}
int main(){
//	freopen("in.txt","r",stdin);
	scanf("%d%d",&n,&m);
	for(int i=1;i<=n;++i)
		for(int j=1;j<=m;++j)
			scanf("%d",&a[i][j]),ans=max(ans,a[i][j]);
	ptr=1,nptr=0,tot[ptr]=1;
	for(int i=1;i<=n;++i){
		for(int j=1;j<=tot[ptr];++j)status[ptr][j]<<=2;
		for(int j=1;j<=m;++j){
			swap(ptr,nptr);
			tot[ptr]=0;
//			printf("[%d]",tot[nptr]);
			memset(head,0,sizeof(head));
			for(int k=1,c1;k<=tot[nptr];++k){
				int st=status[nptr][k];
				if(st>=(1<<bit(m+1)))continue;
				int x=dp[nptr][k];
				int p=(st>>bit(j-1))&3,q=(st>>bit(j))&3;
				int xt=st-(p<<bit(j-1))-(q<<bit(j));
				if(p==0&&q==0){
					add(st,x);
					add(st+(3<<bit(j-1)),x+a[i][j]);
					add(st+(3<<bit(j)),x+a[i][j]);
					add(st+(1<<bit(j-1))+(2<<bit(j)),x+a[i][j]);
				} else if(p==0&&q>0){
					add(st,x+a[i][j]);
					add(st+(q<<bit(j-1))-(q<<bit(j)),x+a[i][j]);
	
					if(q!=3)add(replace(st-(q<<bit(j)),conn(st,j,q),3),x+a[i][j]);
					else if(!xt)ans=max(ans,x+a[i][j]);
				} else if(p>0&&q==0){
					add(st,x+a[i][j]);
					add(st-(p<<bit(j-1))+(p<<bit(j)),x+a[i][j]);
					
					if(p!=3)add(replace(st-(p<<bit(j-1)),conn(st,j,p),3),x+a[i][j]);
					else if(!xt)ans=max(ans,x+a[i][j]);
				} 
				else if(p==q&&p!=3){ add(replace(st-(p<<bit(j-1))-(q<<bit(j)),conn(st,j,p),p),x+a[i][j]); } 
				else if(p==2&&q==1){ add(st-(p<<bit(j-1))-(q<<bit(j)),x+a[i][j]); }
				else if(p==3&&q==3){ if(!xt)ans=max(ans,x+a[i][j]); } 
				else if(p==3&&q!=3){ add(replace(st-(p<<bit(j-1))-(q<<bit(j)),conn(st,j,q),3),x+a[i][j]); }
				else if(p!=3&&q==3){ add(replace(st-(p<<bit(j-1))-(q<<bit(j)),conn(st,j,p),3),x+a[i][j]); }
				
			}
		}
	}
    printf("%d",ans); 
}



  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值