T1:。。略
T2:。。。略
T3:。。。。还是说一下吧。
分类讨论写个搜索,剪下枝,也很水。。
#include<bits/stdc++.h>
using namespace std;
const int MAXN=1e2+5;
int ma[MAXN][MAXN];//-1无色 0红色 1黄色
int ans[MAXN][MAXN];
int fx[]={1,-1,0,0},fy[]={0,0,1,-1};
int n,m;
void dfs(int x,int y,int c,int use){//use 0当前格没用 1用了魔法
for(int i=0;i<4;i++){
if(x+fx[i]<1||x+fx[i]>m||y+fy[i]<1||y+fy[i]>m)continue;
if(!use){
if(ma[x+fx[i]][y+fy[i]]==c&&ans[x+fx[i]][y+fy[i]]>ans[x][y]){
ans[x+fx[i]][y+fy[i]]=ans[x][y];
dfs(x+fx[i],y+fy[i],c,0);
}
if(ma[x+fx[i]][y+fy[i]]!=c&&ma[x+fx[i]][y+fy[i]]!=-1&&ans[x+fx[i]][y+fy[i]]>ans[x][y]+1){
ans[x+fx[i]][y+fy[i]]=ans[x][y]+1;
dfs(x+fx[i],y+fy[i],c^1,0);
}
if(ma[x+fx[i]][y+fy[i]]==-1&&ans[x+fx[i]][y+fy[i]]>ans[x][y]+2){
ans[x+fx[i]][y+fy[i]]=ans[x][y]+2;
dfs(x+fx[i],y+fy[i],c,1);
}
}
else{
if(ma[x+fx[i]][y+fy[i]]!=-1&&ma[x+fx[i]][y+fy[i]]==c&&ans[x+fx[i]][y+fy[i]]>ans[x][y]){
ans[x+fx[i]][y+fy[i]]=ans[x][y];
dfs(x+fx[i],y+fy[i],c,0);
}
if(ma[x+fx[i]][y+fy[i]]!=-1&&ma[x+fx[i]][y+fy[i]]!=c&&ans[x+fx[i]][y+fy[i]]>ans[x][y]+1){
ans[x+fx[i]][y+fy[i]]=ans[x][y]+1;
dfs(x+fx[i],y+fy[i],c^1,0);
}
}
}
}
int main(){
memset(ma,-1,sizeof(ma));
memset(ans,0x7f,sizeof(ans));
scanf("%d%d",&m,&n);
for(int i=1;i<=n;i++){
int x,y,z;
scanf("%d%d%d",&x,&y,&z);
ma[x][y]=z;
}
ans[1][1]=0;
dfs(1,1,ma[1][1],0);
if(ans[m][m]!=2139062143)printf("%d\n",ans[m][m]);
else printf("-1\n");
return 0;
}
T4:看到题,最暴力的方法:直接枚举金币去搜索。
如何优化?首先看到一段单调区间,我们可以二分答案。这样可以拿到50分。
100分:我们发现位置也是连续递增的,并且50分做法的状态转移方程是
f【i】=max(f【j】)+w【i】。(0<=j<i) 形如这样的状态转移方程,我们如果循环查找f【j】显然会重复。如何不重复呢?用单调队列去优化。实现一个队列,随时可以O(1)查询队列中最大(最小)元素。
可以用STL中2个deque来实现(常数大)qaq 用STLdeque在洛谷上被卡成90分,计蒜客AC。
这样转移的时候,维护单调队列可以随时查询最大的f【j】。每次Dp是O(n)复杂度,整体复杂度O(log(ans)n)
#include<bits/stdc++.h>
using namespace std;
#define ll long long
const ll MAXN=5e5+100;
const ll INF=(1ll<<60);
ll n,d,k;
ll pos[MAXN],w[MAXN],f[MAXN];
bool flag=0;
struct mque{
deque<ll>m,q;
inline void push(ll x){
q.push_back(x);
while(m.size()&&m.back()<x)m.pop_back();
m.push_back(x);
}
inline void pop(){
ll x=q.front();
q.pop_front();
if(x==m.front())m.pop_front();
}
inline ll top(){
return m.front();
}
inline ll size(){
return m.size();
}
}mq;
bool check(ll minn,ll maxx,ll df){
while(mq.size())mq.pop();
memset(f,0,sizeof(f));
f[0]=0;
ll l=0,r=0;
for(int i=1;i<=n;i++){// cout<<i<<"ok"<<endl;
while(pos[i]-pos[l]>=minn){
mq.push(f[l]);l++;
}
while(pos[i]-pos[r]>maxx){
r++;mq.pop();
}
if(!mq.size())f[i]=-INF;
else{
f[i]=mq.top()+w[i];//cout<<endl;cout<<f[i]<<endl;
// cout<<i<<" "<<f[i]<<endl;
if(f[i]>=df){
flag=1;return 1;
}
}
}
return 0;
}
int main(){
scanf("%lld%lld%lld",&n,&d,&k);
for(ll i=1;i<=n;i++){
scanf("%lld%lld",&pos[i],&w[i]);
}
ll l=0,r=pos[n];
while(l+1!=r){
ll mid=(l+r)>>1;
// cout<<"mid:"<<mid<<endl;
ll xiao=d-mid,da=d+mid;
if(xiao<1)xiao=1;
if(check(xiao,da,k))r=mid;
else l=mid;
}
// check(5,155,1096);
if(flag)printf("%lld\n",r);
else printf("-1\n");
return 0;
}