求助状压DP入门
  • 板块灌水区
  • 楼主pengyule
  • 当前回复0
  • 已保存回复0
  • 发布时间2021/2/15 17:40
  • 上次更新2023/11/5 03:14:45
查看原帖
求助状压DP入门
300078
pengyule楼主2021/2/15 17:40

rt,外网题,但它是CEOI2002,http://poj.org/problem?id=1038,状压DP入门题,但不知道为什么一些数据过不了,比如:

1
110 5 7
50 3
52 1
70 4
85 4
9 1
76 5
12 1

因为感觉题目本应挺简单,所以放到灌水区问……

望好心人救助!

#include <bits/stdc++.h>
#define int short 
using namespace std;
struct node { int s1,s2,occ1,occ2; }options[275];
int p[151],cnt[1024],f[151][275][275];
int max(int a,int b){return a>b?a:b;}
signed main()
{
	int T;
	cin>>T;
	while(T--){
		memset(cnt,0,sizeof(cnt));
		memset(p,0,sizeof(p));
		memset(f,0,sizeof(f));
		int n,m,k,tx,ty,num=0;
		cin>>n>>m>>k;
		for(int i=1;i<=k;i++){
			cin>>tx>>ty;
			p[tx]|=(1<<m-ty);
		}
		p[n+1]=(1<<m)-1;
		if(n==1){cout<<"0\n";continue;}
		for(int s=0,x=0;s<(1<<m);s++,x=s) while(x) cnt[s]+=(x&1),x>>=1;
		for(int s1=0;s1<(1<<m);s1++) if(!(s1&(s1>>1)|s1&(s1>>2)|(s1>>1)&(s1>>2)) && !(s1&1) && !(s1&2))
			for(int s2=0;s2<(1<<m);s2++) if(!(s2&(s2>>1)) && !(s2&1)){
				int occ1=s1|(s1>>1)|(s1>>2),occ2=s2|(s2>>1);
				if(occ1&occ2) continue;
				options[++num]={s1,s2,occ1,occ2};
			}
		for(int i=1;i<=num;i++){
			if((options[i].occ1|options[i].occ2)&p[1]) continue;
			if((options[i].occ1&p[2]) || (options[i].occ2&p[2]) || (options[i].occ2&p[3])) continue;
			f[1][1][i]=cnt[options[i].s1]+cnt[options[i].s2];
		}
		if(n==2){
			int ans=0;
			for(int i=1;i<=num;i++) ans=max(ans,f[1][1][i]);
			cout<<ans<<endl;
			continue;
		}
		for(int x=1;x<=num;x++) if(x==1 || f[1][1][x])
			for(int y=1;y<=num;y++){
				if((options[y].occ1|options[y].occ2)&p[2]) continue;
				if((options[y].occ1&p[3]) || (options[y].occ2&p[3]) || (options[y].occ2&p[4])) continue;
				if((options[x].occ1|options[x].occ2)&(options[y].occ1|options[y].occ2)) continue;
				f[2][x][y]=f[1][1][x]+cnt[options[y].s1]+cnt[options[y].s2];
			}
		for(int i=3;i<=n-1;i++)
			for(int x=1;x<=num;x++)
				for(int y=1;y<=num;y++) if(f[i-1][x][y])
					for(int z=1;z<=num;z++){
						if((options[z].occ1|options[z].occ2)&p[z]) continue;
						if((options[z].occ1&p[i+1]) || (options[z].occ2&p[i+1]) || (options[z].occ2&p[i+2])) continue;
						if(options[x].occ2&(options[z].occ1|options[z].occ2)) continue;
						if((options[y].occ1|options[y].occ2)&(options[z].occ1|options[z].occ2)) continue;
						f[i][y][z]=max(f[i][y][z],f[i-1][x][y]+cnt[options[z].s1]+cnt[options[z].s2]);
					}
		int ans=0;
		/*for(int i=1;i<n;i++){int dd=0;
		for(int x=1;x<=num;x++) for(int y=1;y<=num;y++)dd=max(dd,f[i][x][y]);cout<<dd<<endl;
		}*/
		for(int x=1;x<=num;x++) for(int y=1;y<=num;y++) ans=max(ans,f[n-1][x][y]);
		cout<<ans<<endl;
	}
	return 0;
} 
2021/2/15 17:40
加载中...