[CF936D]World of Tank

Posted StaroForgin

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了[CF936D]World of Tank相关的知识,希望对你有一定的参考价值。

World of Tank

题解

相当有趣的 d p dp dp题。

显然,如果我们要开炮击毁一个建筑,我们是可以提前在许多个位置开炮的,只要 CD 好了就可以开炮。
如果我们要将 CD 放到状态中的话,是相当麻烦的,毕竟 CD 1 0 9 10^9 109级别的。
事实上这里有一种更好地方法,我们可以不这样记录,我们记录我们可以存储多少的 CD 不用,等着撞到了障碍物,再将这些存着的 CD 消耗掉,表示在这些 CD 满时就打炮,再继续存储剩余的 CD
这样就可以将我们的 CD 放到 d p dp dp之里面,显然 CD 值是屯的越多越好的,所以我们取得肯定是 d p dp dp值的最大值。
在换道的时候,由于你没法提前开炮了,只能冷却你的炮,所以这时候需要将 d p dp dp值与 t t t m i n min min
最后我们可以通过 d p dp dp值还原出我们的操作路径。

但这样 d p dp dp状态还是太多了, n n n 1 0 9 10^9 109级别的。
我们发现我们转道肯定只会在障碍物之后转,而开炮有与状态无关。
所以我们只需要将所有的障碍物和其后一个位置加入 d p dp dp状态,离散化一下就只有 m 1 + m 2 m1+m2 m1+m2级别的状态了。

时间复杂度 O ( ( m 1 + m 2 ) log ⁡   ( m 1 + m 2 ) ) O\\left((m1+m2)\\log\\,(m1+m2)\\right) O((m1+m2)log(m1+m2))

源码

#include<bits/stdc++.h>
using namespace std;
#define MAXN 2000005
#define lowbit(x) (x&-x)
#define reg register
#define pb push_back
#define mkpr make_pair
#define fir first
#define sec second
typedef long long LL;
typedef unsigned long long uLL; 
typedef long double ld;
typedef pair<int,int> pii;
const LL INF=0x7f7f7f7f7f7f7f7f;
const int mo=1e9+7;
const int inv2=5e8+4;
const int jzm=23333;
const int zero=20000;
const int lim=1000000;
const int orG=3,ivG=334845270;
const double Pi=acos(-1.0);
const double eps=1e-12;
template<typename _T>
_T Fabs(_T x)return x<0?-x:x;
template<typename _T>
void read(_T &x)
	_T f=1;x=0;char s=getchar();
	while(s>'9'||s<'0')if(s=='-')f=-1;s=getchar();
	while('0'<=s&&s<='9')x=(x<<3)+(x<<1)+(s^48);s=getchar();
	x*=f;

template<typename _T>
void print(_T x)if(x<0)x=(~x)+1;putchar('-');if(x>9)print(x/10);putchar(x%10+'0');
int gcd(int a,int b)return !b?a:gcd(b,a%b);
int add(int x,int y,int p)return x+y<p?x+y:x+y-p;
void Add(int &x,int y,int p)x=add(x,y,p);
int qkpow(int a,int s,int p)int t=1;while(s)if(s&1)t=1ll*t*a%p;a=1ll*a*a%p;s>>=1;return t;
int n,m1,m2,b[MAXN],tot,cnt,pre[MAXN][2],dp[MAXN][2],t;
bool maze[MAXN][2];
vector<int>ans1;
vector<pii>ans2;
struct mingint x,y;s[MAXN];
signed main()
	read(n);read(m1);read(m2);read(t);b[++tot]=1;
	for(int i=1,x;i<=m1;i++)read(x),s[++cnt]=(ming)x,0,b[++tot]=x,b[++tot]=x+1;
	for(int i=1,x;i<=m2;i++)read(x),s[++cnt]=(ming)x,1,b[++tot]=x,b[++tot]=x+1;
	sort(b+1,b+tot+1);tot=unique(b+1,b+tot+1)-b-1;
	for(int i=1;i<=cnt;i++)s[i].x=lower_bound(b+1,b+tot+1,s[i].x)-b,maze[s[i].x][s[i].y]=1;
	memset(dp,-0x3f,sizeof(dp));
	dp[0][0]=0;
	for(int i=1;i<=tot;i++)
		int dif=b[i]-b[i-1];
		for(int j=0;j<2;j++)
			if(!maze[i][j]&&dp[i-1][j]>=0)
				dp[i][j]=max(dp[i][j],dp[i-1][j]+dif);
				if(dp[i-1][j]+dif==dp[i][j])pre[i][j]=0;
			
			if(maze[i][j]&&dp[i-1][j]+dif>t)
				dp[i][j]=max(dp[i][j],dp[i-1][j]-t+dif);
				if(dp[i-1][j]-t+dif==dp[i][j])pre[i][j]=0;	
			
			if(!maze[i][j]&&!maze[i-1][j]&&dp[i-1][j^1]>=0)
				dp[i][j]=max(dp[i][j],min(dp[i-1][j^1],t)+dif);
				if(min(dp[i-1][j^1],t)+dif==dp[i][j])pre[i][j]=1;
			
			if(maze[i][j]&&!maze[i-1][j]&&dp[i-1][j^1]+dif>t)
				dp[i][j]=max(dp[i][j],min(dp[i-1][j^1],t)+dif-t);
				if(min(dp[i-1][j^1],t)+dif-t==dp[i][j])pre[i][j]=1;
			
		
	
	if(dp[tot][0]<0&&dp[tot][1]<0)puts("No");return 0;
	int now=dp[tot][0]>=0?0:1,pos=tot,siz;
	while(pos)
		int nxt=now^pre[pos][now];if(nxt^now)ans1.pb(b[pos-1]);
		if(maze[pos][now])ans2.pb(mkpr(b[pos]-dp[pos][now],2-(now^1)));
		now=nxt;pos--;
	
	puts("Yes");
	printf("%d\\n",siz=ans1.size());reverse(ans1.begin(),ans1.end());
	for(int i=0;i<siz;i++)printf("%d ",ans1[i]);puts("");
	printf("%d\\n",siz=ans2.size());reverse(ans2.begin(),ans2.end());
	for(int i=0;i<siz;i++)printf("%d %d\\n",ans2[i].fir,ans2[i].sec);
	return 0;  

谢谢!!!

以上是关于[CF936D]World of Tank的主要内容,如果未能解决你的问题,请参考以下文章

CF1321-World of Darkraft: Battle for Azathoth (线段树+二维偏序)

CF996B World Cup 思维 第十四 *

CF 996B World Cup 找规律/模拟

CF 990B B. Micro-World数组操作/贪心/STL/二分搜索

CF游戏出现out of memory 怎么解决

sh World of Warships的mac应用程序