洛谷 P2704 [NOI2001] 炮兵阵地(状态压缩dp)

题目链接:P1879 [USACO06NOV]Corn Fields G

题解:做本题前建议先做P1879 [USACO06NOV]Corn Fields G,题解也就在该篇前。

这题和前面那题很相似但又不一样,可以说是上题的拓展版本,我们发现如果继续用dp[i][j]来表示第i行的状态为j的情况是炮兵的最大数量,此时我们没有办法确定该点状态是否可行,因为可能上上行该点有炮兵导致不合法,我们就会想到用dp[i][j][k]表示第i行时,当前状态为j,上一行状态为k时炮兵最大数量,但是一想,复杂度n*(2^m)^3,有1e11,感觉不太对劲,但是做过之前那题就应该知道,虽然没维枚举的有1e3,但实际上可行状态非常少,光要求每行中两个点至少相距离2格,就把实际可行情况降低至2^(m/3),这时实际复杂度就不那么大了,这部分可能很容易被忽视,其他部分和上题差不多,提前处理下每个状态中1的数量,假设当前状态维j判断左右len格子内有无点即j&(j<

细节和不懂见代码:

#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include 
#include/*
	#ifndef local
	#define endl '\n'
#endif */
#define mkp make_pair
using namespace std;
using std::bitset;
typedef long long ll;
typedef long double ld;
const int inf=0x3f3f3f3f;
const ll MAXN=2e6+10;
const ll N=2e5+100;
const ll mod=1e9+7;
const ll hash_p1=1610612741;
const ll hash_p2=805306457;
const ll hash_p3=402653189;
//-----------------------------------------------------------------------------------------------------------------*/
// ll head[MAXN],net[MAXN],to[MAXN],edge[MAXN]/*流量*/,cost[MAXN]//费用;
/* 
void add(ll u,ll v,ll w,ll s){
	to[++cnt]=v;net[cnt]=head[u];edge[cnt]=w;cost[cnt]=s;head[u]=cnt;
	to[++cnt]=u;net[cnt]=head[v];edge[cnt]=0;cost[cnt]=-s;head[v]=cnt;
}
struct elemt{
	int p,v;
};
-----------------------------------
求[1,MAXN]组合式和逆元 
ll mi(ll a,ll b){
	ll res=1;
	while(b){
		if(b%2){
			res=res*a%mod;
		}	
		a=a*a%mod;
		b/=2;
	}
	return res;
}
ll fac[MAXN+10],inv[MAXN+10]
ll C(int m,int n){//组合式C(m,n); 
	if(!n){
		return 1;
	}
	return fac[m]*(inv[n]*inv[m-n]%mod)%mod;
}
fac[0]=1;inv[0]=1;
for(ll i=1;i<=MAXN;i++){
	fac[i]=(fac[i-1]*i)%mod;
	inv[i]=mi(fac[i],mod-2);
}
---------------------------------
 unordered_mapmp;
//优先队列默认小顶堆 , greater --小顶堆  less --大顶堆  
priority_queue,comp>q;
struct comp{
	public:
		bool operator()(elemt v1,elemt v2){
			return v1.v::iterator it=st.begin();
*/
//emplace_back()  等于push_back(),但效率更高,传输pair时emplace_back(i,j)==push_back({i,j}) 
// vector>edge; 二维虚拟储存坐标 
//-----------------------------------------------------------------------------------------------------------------*/
  //mapmp[N]; 
  //emplace_back() 
ll dp[5][1100][1100];//枚举到第i行,当前状态为j(1为有炮兵,0为无),上一行状态为k时炮兵的数量
int a[110];
int num[1100];
int get_num(int k){
	int res=0;
	while(k){
		if(k%2){
			res++;
		}
		k/=2;
	}
	return res;
}
int main(){
/*cout<>n>>m;
	for(int i=1;i<=n;i++){
		for(int j=1;j<=m;j++){
			char d;
			cin>>d;
			if(d=='P'){
				a[i]+=1<<(j-1);//每行山地情况转化成二进制
			}
		}
	}
	for(int i=0;i<(1<

你可能感兴趣的:(DP,动态规划,leetcode,算法)