维修数列

(传送门)

题意

对于一个数列,支持插入,删除,修改,翻转,求和,求最大子列的操作

分析

又是对于一个数列的各种操作,考察splay的各种操作(NOI这几年真爱考splay),没什么好分析的,看代码。

涉及操作比较多也比较全,此题代码可当做splay的模板

代码

#include  <bits/stdc++.h>
using namespace std;const int INF=0x3f3f3f3f;
const int MAXN=1e6+5;int n,m,rt,cnt,a[MAXN];
int id[MAXN],fa[MAXN],son[MAXN][2];
int sum[MAXN],size[MAXN],v[MAXN],mx[MAXN],lx[MAXN],rx[MAXN];
bool tag[MAXN],rev[MAXN];
queue<int> Q;void update(int x)
{int l=son[x][0],r=son[x][1];sum[x]=sum[l]+sum[r]+v[x];size[x]=size[l]+size[r]+1;mx[x]=max(mx[l],mx[r]);mx[x]=max(mx[x],rx[l]+v[x]+lx[r]);lx[x]=max(lx[l],sum[l]+v[x]+lx[r]);rx[x]=max(rx[r],sum[r]+v[x]+rx[l]);
}void pushdown(int x)
{int l=son[x][0],r=son[x][1];if(tag[x]){rev[x]=tag[x]=0;if(l) tag[l]=1,v[l]=v[x],sum[l]=v[x]*size[l];if(r) tag[r]=1,v[r]=v[x],sum[r]=v[x]*size[r];if(v[x]>=0){if(l) lx[l]=rx[l]=mx[l]=sum[l];if(r) lx[r]=rx[r]=mx[r]=sum[r];}else {if(l) lx[l]=rx[l]=0,mx[l]=v[x];if(r) lx[r]=rx[r]=0,mx[r]=v[x];}}if(rev[x]){rev[x]^=1,rev[l]^=1,rev[r]^=1;swap(lx[l],rx[l]),swap(lx[r],rx[r]);swap(son[l][0],son[l][1]),swap(son[r][0],son[r][1]);}
}void rotate(int x,int &k)
{int y=fa[x],z=fa[y];int p=(son[y][1]==x),q=p^1;if(y==k) k=x;else son[z][(son[z][1]==y)]=x;fa[son[x][q]]=y;fa[y]=x;fa[x]=z;son[y][p]=son[x][q];son[x][q]=y;update(y);update(x);
}void splay(int x,int &k)
{while(x!=k){int y=fa[x],z=fa[y];if(y!=k){if((son[y][0]==x)^(son[z][0]==y)) rotate(x,k);else rotate(y,k);}rotate(x,k);}
}int find(int x,int rk)
{int l=son[x][0],r=son[x][1];pushdown(x);if(size[l]+1==rk) return x;if(size[l]>=rk) return find(l,rk);else find(r,rk-size[l]-1);
}int split(int k,int tot)
{int x=find(rt,k),y=find(rt,k+tot+1);splay(x,rt);splay(y,son[x][1]);return son[y][0];
}void query(int k,int tot)
{int x=split(k,tot);printf("%d\n",sum[x]);
}void modify(int k,int tot,int val)
{int x=split(k,tot),y=fa[x];v[x]=val;tag[x]=1;sum[x]=size[x]*val;if(val>=0) lx[x]=rx[x]=mx[x]=sum[x];else lx[x]=rx[x]=0,mx[x]=val;update(y);update(fa[y]);
}void rever(int k,int tot)
{int x=split(k,tot),y=fa[x];if(!tag[x]){rev[x]^=1;swap(son[x][0],son[x][1]);swap(lx[x],rx[x]);update(y);update(fa[y]);}
}void rec(int x)
{if(!x) return;int l=son[x][0],r=son[x][1];rec(l),rec(r);Q.push(x);fa[x]=son[x][0]=son[x][1]=0;tag[x]=rev[x]=0;
}void erase(int k,int tot)
{int x=split(k,tot),y=fa[x];rec(x);son[y][0]=0;update(y);update(fa[y]);
}void build(int l,int r,int f)
{if(l>r)return;int mid=(l+r)>>1,now=id[mid],last=id[f];if(l==r){sum[now]=a[l];size[now]=1;tag[now]=rev[now]=0;if(a[l]>=0) lx[now]=rx[now]=mx[now]=a[l];else lx[now]=rx[now]=0,mx[now]=a[l];}else {build(l,mid-1,mid);build(mid+1,r,mid);}v[now]=a[mid];fa[now]=last;update(now);son[last][(mid>=f)]=now;}void insert(int k,int tot)
{for(int i=1;i<=tot;i++)scanf("%d",&a[i]);for(int i=1;i<=tot;i++){if(!Q.empty()) id[i]=Q.front(),Q.pop();else id[i]=++cnt;}build(1,tot,0);int z=id[(1+tot)/2];int x=find(rt,k+1),y=find(rt,k+2);splay(x,rt);splay(y,son[x][1]);fa[z]=y;son[y][0]=z;update(y);update(x);
}int main()
{cin>>n>>m;mx[0]=a[1]=a[n+2]=-INF;for(int i=2;i<=n+1;i++)scanf("%d",&a[i]);for(int i=1;i<=n+2;i++)id[i]=i;build(1,n+2,0);rt=(n+3)>>1;cnt=n+2;while(m--){char ch[10];int k,tot,val;scanf("%s",ch);if(ch[0]=='M' && ch[2]=='X') printf("%d\n",mx[rt]);else{scanf("%d%d",&k,&tot);if(ch[0]=='I') insert(k,tot);if(ch[0]=='D') erase(k,tot);if(ch[0]=='R') rever(k,tot);if(ch[0]=='G') query(k,tot);if(ch[0]=='M'){scanf("%d",&val);modify(k,tot,val);}}    }return 0;
}

瑰丽华尔兹

(传送门)

题意

一个N行M列的矩阵,矩阵中的某些方格是空地,钢琴只可以在空地上滑动。每个时刻,钢琴都会随着船体倾斜的方向向相邻的方格(任意四个方向)滑动一格。每个时刻可以选择施魔法或不施魔法:如果不施魔法,则钢琴会滑动;如果施魔法,则钢琴会原地不动。知道每段时间的船体的倾斜情况。使钢琴在舞厅里滑行路程尽量长

分析

求最多最少之类的问题,显而易见的Dp题目

定义dp[x][y][k]表示第k段时间钢琴停在坐标为(x,y)的格子的时候的滑动距离。每段时间只朝一个方向滑动,所以对于每段时间,状态转移时只需要考虑一个方向。以向南滑动为例: dp[x][y][k]=max{ dp[r][y][k-1]+(x-r) }(0<=x-r<=len),由于只与K-1有关,用滚动数组或直接开二维的数组。于是,状态数是n^3,转移的时间是O(n), 总的复杂度就是 O(n^4)这样显然是超时的。所以考虑优化。

我们知道,对于一类单调性动态规划题目,满足f(x)=opt(const[i]) (bound[x]<=i<=x-1)( 其中bound[x]单调不递减,const[i]是可以根据i在常数时间内确定的唯一常数),可以使用单调队列进行优化。

于是观察状态转移方程,dp[r][y][[k-1]+(x-r)即(dp[r][y][k-1]-r)+x,只与r有关,因此可以使用单调队列优化,转移变为O(1)

或者在比赛时遇到不确定的动态规划题目,不知道能否用单调队列优化时可先写出来,再和复杂度高的程序对拍几组数据,就可以确定能不能使用了(为拿分不择手段。。)

代码

#include <bits/stdc++.h>
using namespace std;const int MAXN=200+5;
const int INF=0x3f3f3f3f;
const int dx[5]={0,-1,1,0,0};
const int dy[5]={0,0,0,-1,1};int n,m,t;
int sx,sy;
char mp[MAXN][MAXN];
int dp[MAXN][MAXN];struct Node
{int val,tag;
} Q[MAXN];
int ans=0;void work(int x,int y,int key,int len)
{int now=0,f=0,r=0;Node tmp;while(1<=x&&x<=n&&1<=y&&y<=m){if(mp[x][y]=='x') f=r=0;else{tmp.val=dp[x][y],tmp.tag=now;while(f<r&&Q[r-1].val+now-Q[r-1].tag<=tmp.val) r--;Q[r++]=tmp;while(f<r&&Q[f].tag+len<now) f++;dp[x][y]=Q[f].val+now-Q[f].tag;ans=max(ans,dp[x][y]);}now++;x+=dx[key],y+=dy[key];}
}int main()
{cin>>n>>m>>sx>>sy>>t;for(int i=1;i<=n;i++)scanf("%s",mp[i]+1);for(int i=1;i<=n;i++)for(int j=1;j<=m;j++)dp[i][j]=-INF;dp[sx][sy]=0;for(int k=1;k<=t;k++){int st,ed,len,ch;scanf("%d%d%d",&st,&ed,&ch);len=ed-st+1;switch(ch){case 1 : for(int j=1;j<=m;j++) work(n,j,1,len); break;case 2 : for(int j=1;j<=m;j++) work(1,j,2,len); break;case 3 : for(int i=1;i<=n;i++) work(i,m,3,len); break;case 4 : for(int i=1;i<=n;i++) work(i,1,4,len); break;}}cout<<ans<<endl;return 0;
}

智慧珠游戏

(传送门)

题意

10*10的等腰直角三角形,有12种零件,其中3联1个,4联3个,5联8个。给你一个残局,要求用剩下的零件填满棋盘。

分析

搜索题

这道题的正解是建立精确覆盖的模型,用Dancing Links来优化搜索,但是用预处理+普通搜索+好一些的剪枝,还是可以涉险过的

注意代码中名为 niubi() 的函数,用它来剪枝简直牛逼,没有这一步会超时超的很厉害

代码

#include <bits/stdc++.h>
using namespace std;const int MAXN=150;struct Ret
{int tot,cnt,x[8][5],y[8][5];Ret():tot(0),cnt(0){memset(x,0,sizeof(x)),memset(y,0,sizeof(y));}Ret(int p){switch(p){case 'A': cnt=4,tot=2; x[0][0]=1,y[0][0]=0; x[0][1]=0,y[0][1]=1;x[1][0]=1,y[1][0]=0; x[1][1]=1,y[1][1]=1;x[2][0]=0,y[2][0]=1; x[2][1]=1,y[2][1]=1;x[3][0]=1,y[3][0]=0; x[3][1]=1,y[3][1]=-1;break;case 'B': cnt=2,tot=3;x[0][0]=0,y[0][0]=1; x[0][1]=0,y[0][1]=2; x[0][2]=0,y[0][2]=3;x[1][0]=1,y[1][0]=0; x[1][1]=2,y[1][1]=0; x[1][2]=3,y[1][2]=0;break;case 'C': cnt=8,tot=3;x[0][0]=0,y[0][0]=1; x[0][1]=0,y[0][1]=2; x[0][2]=1,y[0][2]=0;x[1][0]=0,y[1][0]=1; x[1][1]=1,y[1][1]=1; x[1][2]=2,y[1][2]=1;x[2][0]=1,y[2][0]=-2; x[2][1]=1,y[2][1]=-1; x[2][2]=1,y[2][2]=0;x[3][0]=1,y[3][0]=0; x[3][1]=2,y[3][1]=0; x[3][2]=2,y[3][2]=1;x[4][0]=1,y[4][0]=0; x[4][1]=2,y[4][1]=0; x[4][2]=2,y[4][2]=-1;x[5][0]=1,y[5][0]=0; x[5][1]=1,y[5][1]=1; x[5][2]=1,y[5][2]=2;x[6][0]=0,y[6][0]=1; x[6][1]=1,y[6][1]=0; x[6][2]=2,y[6][2]=0;x[7][0]=0,y[7][0]=1; x[7][1]=0,y[7][1]=2; x[7][2]=1,y[7][2]=2;break;case 'D': cnt=1,tot=3;x[0][0]=0,y[0][0]=1; x[0][1]=1,y[0][1]=0; x[0][2]=1,y[0][2]=1;break;case 'E': cnt=4,tot=4;x[0][0]=0,y[0][0]=1; x[0][1]=0,y[0][1]=2; x[0][2]=1,y[0][2]=0; x[0][3]=2,y[0][3]=0;x[1][0]=1,y[1][0]=0; x[1][1]=2,y[1][1]=0; x[1][2]=2,y[1][2]=1; x[1][3]=2,y[1][3]=2;x[2][0]=0,y[2][0]=1; x[2][1]=0,y[2][1]=2; x[2][2]=1,y[2][2]=2; x[2][3]=2,y[2][3]=2;x[3][0]=2,y[3][0]=-2; x[3][1]=2,y[3][1]=-1; x[3][2]=2,y[3][2]=0; x[3][3]=1,y[3][3]=0;break;case 'F': cnt=8,tot=4;x[0][0]=0,y[0][0]=1; x[0][1]=1,y[0][1]=1; x[0][2]=0,y[0][2]=2; x[0][3]=0,y[0][3]=3;x[1][0]=1,y[1][0]=0; x[1][1]=2,y[1][1]=0; x[1][2]=3,y[1][2]=0; x[1][3]=2,y[1][3]=1;x[2][0]=1,y[2][0]=-2; x[2][1]=1,y[2][1]=-1; x[2][2]=1,y[2][2]=0; x[2][3]=1,y[2][3]=1;x[3][0]=1,y[3][0]=-1; x[3][1]=1,y[3][1]=0; x[3][2]=2,y[3][2]=0; x[3][3]=3,y[3][3]=0;x[4][0]=1,y[4][0]=0; x[4][1]=1,y[4][1]=1; x[4][2]=2,y[4][2]=0; x[4][3]=3,y[4][3]=0;x[5][0]=1,y[5][0]=-1; x[5][1]=1,y[5][1]=0; x[5][2]=1,y[5][2]=1; x[5][3]=1,y[5][3]=2;x[6][0]=1,y[6][0]=0; x[6][1]=2,y[6][1]=0; x[6][2]=1,y[6][2]=-1; x[6][3]=3,y[6][3]=0;x[7][0]=0,y[7][0]=1; x[7][1]=0,y[7][1]=2; x[7][2]=1,y[7][2]=2; x[7][3]=0,y[7][3]=3;break;case 'G': cnt=4,tot=4;x[0][0]=1,y[0][0]=0; x[0][1]=0,y[0][1]=1; x[0][2]=0,y[0][2]=2; x[0][3]=1,y[0][3]=2;x[1][0]=0,y[1][0]=1; x[1][1]=1,y[1][1]=0; x[1][2]=2,y[1][2]=0; x[1][3]=2,y[1][3]=1;x[2][0]=1,y[2][0]=0; x[2][1]=1,y[2][1]=1; x[2][2]=1,y[2][2]=2; x[2][3]=0,y[2][3]=2;x[3][0]=0,y[3][0]=1; x[3][1]=1,y[3][1]=1; x[3][2]=2,y[3][2]=1; x[3][3]=2,y[3][3]=0;break;case 'H': cnt=8,tot=4;x[0][0]=0,y[0][0]=1; x[0][1]=1,y[0][1]=0; x[0][2]=1,y[0][2]=1; x[0][3]=0,y[0][3]=2;x[1][0]=1,y[1][0]=1; x[1][1]=1,y[1][1]=0; x[1][2]=2,y[1][2]=1; x[1][3]=2,y[1][3]=0;x[2][0]=0,y[2][0]=1; x[2][1]=1,y[2][1]=0; x[2][2]=1,y[2][2]=1; x[2][3]=1,y[2][3]=-1;x[3][0]=0,y[3][0]=1; x[3][1]=1,y[3][1]=0; x[3][2]=1,y[3][2]=1; x[3][3]=2,y[3][3]=1;x[4][0]=0,y[4][0]=1; x[4][1]=1,y[4][1]=0; x[4][2]=1,y[4][2]=1; x[4][3]=2,y[4][3]=0;x[5][0]=0,y[5][0]=1; x[5][1]=1,y[5][1]=0; x[5][2]=1,y[5][2]=1; x[5][3]=1,y[5][3]=2;x[6][0]=1,y[6][0]=-1; x[6][1]=1,y[6][1]=0; x[6][2]=2,y[6][2]=-1; x[6][3]=2,y[6][3]=0;x[7][0]=0,y[7][0]=1; x[7][1]=0,y[7][1]=2; x[7][2]=1,y[7][2]=1; x[7][3]=1,y[7][3]=2;break;case 'I': cnt=8,tot=4;x[0][0]=0,y[0][0]=1; x[0][1]=0,y[0][1]=2; x[0][2]=1,y[0][2]=2; x[0][3]=1,y[0][3]=3;x[1][0]=1,y[1][0]=-1; x[1][1]=1,y[1][1]=0; x[1][2]=2,y[1][2]=-1; x[1][3]=3,y[1][3]=-1;x[2][0]=0,y[2][0]=1; x[2][1]=1,y[2][1]=1; x[2][2]=1,y[2][2]=2; x[2][3]=1,y[2][3]=3;x[3][0]=1,y[3][0]=0; x[3][1]=2,y[3][1]=0; x[3][2]=2,y[3][2]=-1; x[3][3]=3,y[3][3]=-1;x[4][0]=1,y[4][0]=0; x[4][1]=2,y[4][1]=0; x[4][2]=2,y[4][2]=1; x[4][3]=3,y[4][3]=1;x[5][0]=1,y[5][0]=-2; x[5][1]=1,y[5][1]=-1; x[5][2]=1,y[5][2]=0; x[5][3]=0,y[5][3]=1;x[6][0]=1,y[6][0]=0; x[6][1]=1,y[6][1]=1; x[6][2]=2,y[6][2]=1; x[6][3]=3,y[6][3]=1;x[7][0]=1,y[7][0]=0; x[7][1]=1,y[7][1]=-1; x[7][2]=0,y[7][2]=1; x[7][3]=0,y[7][3]=2;break;case 'J': cnt=1,tot=4;x[0][0]=1,y[0][0]=-1; x[0][1]=1,y[0][1]=0; x[0][2]=1,y[0][2]=1; x[0][3]=2,y[0][3]=0;break;case 'K': cnt=4,tot=4;x[0][0]=1,y[0][0]=0; x[0][1]=1,y[0][1]=1; x[0][2]=2,y[0][2]=1; x[0][3]=2,y[0][3]=2;x[1][0]=1,y[1][0]=0; x[1][1]=1,y[1][1]=-1; x[1][2]=2,y[1][2]=-1; x[1][3]=2,y[1][3]=-2;x[2][0]=0,y[2][0]=1; x[2][1]=1,y[2][1]=1; x[2][2]=1,y[2][2]=2; x[2][3]=2,y[2][3]=2;x[3][0]=0,y[3][0]=1; x[3][1]=1,y[3][1]=0; x[3][2]=1,y[3][2]=-1; x[3][3]=2,y[3][3]=-1;break;case 'L': cnt=8,tot=4;x[0][0]=0,y[0][0]=1; x[0][1]=0,y[0][1]=2; x[0][2]=0,y[0][2]=3; x[0][3]=1,y[0][3]=0;x[1][0]=0,y[1][0]=1; x[1][1]=1,y[1][1]=1; x[1][2]=2,y[1][2]=1; x[1][3]=3,y[1][3]=1;x[2][0]=1,y[2][0]=0; x[2][1]=1,y[2][1]=-1; x[2][2]=1,y[2][2]=-2; x[2][3]=1,y[2][3]=-3;x[3][0]=1,y[3][0]=0; x[3][1]=2,y[3][1]=0; x[3][2]=3,y[3][2]=0; x[3][3]=3,y[3][3]=1;x[4][0]=1,y[4][0]=0; x[4][1]=2,y[4][1]=0; x[4][2]=3,y[4][2]=0; x[4][3]=3,y[4][3]=-1;x[5][0]=1,y[5][0]=0; x[5][1]=1,y[5][1]=1; x[5][2]=1,y[5][2]=2; x[5][3]=1,y[5][3]=3;x[6][0]=1,y[6][0]=0; x[6][1]=2,y[6][1]=0; x[6][2]=3,y[6][2]=0; x[6][3]=0,y[6][3]=1;x[7][0]=0,y[7][0]=1; x[7][1]=0,y[7][1]=2; x[7][2]=0,y[7][2]=3; x[7][3]=1,y[7][3]=3;break;}}
}opt[MAXN];
char a[10][10];
bool used[MAXN];bool ok(int x,int y,Ret &op,int l)
{for(int i=0;i<op.tot;i++)if(x+op.x[l][i]<1||y+op.y[l][i]<1||a[x+op.x[l][i]][y+op.y[l][i]]!='.') return 0;return 1;
}void put(int x,int y,Ret &op,int l,char c)
{for(int i=0;i<op.tot;i++)a[x+op.x[l][i]][y+op.y[l][i]]=c;
}bool dfs(int i,int j)
{if(i<j) return dfs(i+1,1); if(i>10){for(int k=1;k<=10;k++)puts(a[k]+1);return 1;}if(a[i][j]!='.') return dfs(i,j+1);for(int k='A';k<='L';k++)if(!used[k]){used[k]=1;a[i][j]=k;for(int l=0;l<opt[k].cnt;l++)if(ok(i,j,opt[k],l)){put(i,j,opt[k],l,k);if(dfs(i,j+1)) return 1;put(i,j,opt[k],l,'.');}used[k]=0;a[i][j]='.';} return 0;
}bool niubi()
{for(int i=1;i<=10;i++)for(int j=1;j<=i;j++)if(a[i][j]=='.'&&a[i][j+1]=='.'&&a[i][j-1]!='.'&&a[i][j+2]!='.'&&a[i-1][j]!='.'&&a[i-1][j+1]!='.'&&a[i+1][j]!='.'&&a[i+1][j+1]!='.'||a[i][j]=='.'&&a[i+1][j]=='.'&&a[i-1][j]!='.'&&a[i+2][j]!='.'&&a[i][j-1]!='.'&&a[i+1][j-1]!='.'&&a[i][j+1]!='.'&&a[i+1][j+1]!='.') return 0;return 1;
}int main()
{for(int i=1;<=10)scanf("%s",a[i]+1);for(int i=1;<=10)for(int j=1;j<=i;j++)if(a[i][j]!='.')used[a[i][j]]=1;for(int i='A';i<='L';i++)opt[i]=Ret(i);if(!niubi()||!dfs(1,1))puts("No solution");return 0;
}

月下柠檬树

(传送门)

题意

给了个立体的模型,求投影面积,自己画图转化一下就是求圆并面积

分析

圆并面积用自适应Simpson积分来求,这也是一道比较裸的模板题

关键是圆的公切线的求法:首先延长圆的切线求l,再求θ,最后用相似三角形。

代码

#include <bits/stdc++.h>
using namespace std;const int MAXN=500+5;
const double eps=1e-5;
double h[MAXN],s[MAXN],r[MAXN],alpha,l1=0,r1=0;
double sqr(double x){return x*x;}
int n,size=0;
struct S
{double x,y,p,q;
} c[MAXN];double f(double l)
{double t=0.0;for(int i=0;i<n;i++)  if(fabs(s[i]-l)<r[i])t=max(t,sqrt(sqr(r[i])-sqr(s[i]-l)));for(int i=1;i<=size;i++)  if(c[i].x<l&&l<c[i].p)t=max(t,c[i].y+(c[i].q-c[i].y)*(l-c[i].x)/(c[i].p-c[i].x));return t;
}double simpson(double l,double r,double fl,double fmid,double fr)
{return (fl+4*fmid+fr)*(r-l)/6;
}double rsimpson(double l,double r,double fl,double fmid,double fr)
{double m=(l+r)/2;double p=f((l+m)/2),q=f((m+r)/2);double x=simpson(l,r,fl,fmid,fr),y=simpson(l,m,fl,p,fmid),z=simpson(m,r,fmid,q,fr);if(fabs(x-y-z)<eps)   return y+z;else return rsimpson(l,m,fl,p,fmid)+rsimpson(m,r,fmid,q,fr);
}int main()
{scanf("%d%lf",&n,&alpha);alpha=1/tan(alpha);for(int i=0;i<=n;i++){scanf("%lf",&h[i]);if(i) h[i]+=h[i-1];s[i]=h[i]*alpha;}for(int i=0;i<n;i++)  {scanf("%lf",&r[i]);l1=min(l1,s[i]-r[i]);r1=max(r1,s[i]+r[i]);}r[n]=0;for(int i=0;i<n;i++)  {double d=s[i+1]-s[i];if(d>fabs(r[i]-r[i+1]))  {c[++size].x=s[i]-r[i]*(r[i+1]-r[i])/d;c[size].y=sqrt(sqr(r[i])-sqr(c[size].x-s[i]));      c[size].p=s[i+1]-r[i+1]*(r[i+1]-r[i])/d;c[size].q=sqrt(sqr(r[i+1])-sqr(c[size].p-s[i+1]));}}r1=max(r1,s[n]);printf("%.2lf",2*rsimpson(l1,r1,0,f((l1+r1)/2),0));return 0;
}

聪聪与可可

(传送门)

题意

树形的图上,老鼠可以随便走,猫一直向靠近老鼠的方向走(可走两步),求平均多长时间猫可以吃掉老鼠。

分析

这是一道期望Dp。

定义dp[ i ][ j ] 猫在 i ,老鼠在 j ,猫吃到老鼠的期望次数

bfs预处理出下一步走法,

注意:猫可走一步,没吃时可再走一步,当排除了两者只剩一步的可能,后面都选择两步来更新更优

代码

#include <bits/stdc++.h>
using namespace std;const int maxn=1005;
int n,m,s,t;
vector<int> edges[maxn];
double dp[maxn][maxn];//dp[i][j] cc在i,kk在j,cc吃到kk的期望次数
int next[maxn][maxn];//下一步走法void bfs(int s)
{for(int i=1;i<=n;i++)  dp[s][i]=-1;bool vis[maxn];memset(vis,0,sizeof vis);queue<int> Q;Q.push(s);vis[s]=1;while(!Q.empty()){int u=Q.front();  Q.pop();for(int i=0;i<edges[u].size();i++){int v=edges[u][i];if(!vis[v]){vis[v]=1;  Q.push(v);next[s][v] = next[s][u] ? next[s][u] : v;}}}
}double dfs(int i,int j)
{if(dp[i][j]!=-1)  return dp[i][j];if(i==j)  return dp[i][j]=0;if(next[i][j]==j || next[next[i][j]][j]==j)  return dp[i][j]=1;//可走一步,没吃到可再走一步//排除了两者只剩一步的可能,所以后面都选择两步来更新更优dp[i][j]=dfs(next[next[i][j]][j],j);for(int k=0;k<edges[j].size();k++)  dp[i][j] += dfs(next[next[i][j]][j],edges[j][k]);dp[i][j] /= (edges[j].size()+1);return ++dp[i][j];
}int main()
{cin>>n>>m>>s>>t;for(int i=1;i<=m;i++){int u,v;scanf("%d%d",&u,&v);edges[u].push_back(v);edges[v].push_back(u);}for(int i=1;i<=n;i++)  sort(edges[i].begin(),edges[i].end());for(int i=1;i<=n;i++)  bfs(i);printf("%.3lf\n",dfs(s,t));return 0;
}

NOI 2005 题解相关推荐

  1. 【OpenJudge NOI】题解目录

    [OpenJudge NOI]题解目录 OJ链接:OpenJudge NOI 以下为本人做的OJ题解 针对每一道题我都会给出题目考点.解题思路.题解代码.必要时也会给出不同的解题方法. 如有不足之处, ...

  2. NOI 2005 聪聪与可可 题解

    题目传送门 题目大意: 给出一张无向图,起点终点为 S,TS,TS,T,聪聪站在起点,可可站在终点,可可每回合随机走 111 步,也可能不动,聪聪则会每回合沿最短路向他走两步,每回合聪聪先走,问聪聪期 ...

  3. NOI 2005 聪聪可可

    1784 聪聪与可可 2005年NOI全国竞赛 时间限制: 1 s 空间限制: 128000 KB 题目等级 : 大师 Master 题解 题目描述 Description 在一个魔法森林里,住着一只 ...

  4. bzoj 1500 [NOI 2005] 维修数列

    题目大意不多说了 貌似每个苦逼的acmer都要做一下这个splay树的模版题目吧 还是有很多操作的,估计够以后当模版了.... 1 #include <cstdio> 2 #include ...

  5. 解题报告 noi 2005 智慧珠游戏(BT 搜索)

    智慧珠游戏 [问题描述] 智慧珠游戏拼盘由一个三角形盘件和12个形态各异的零件组成.拼盘的盘件如图1所示: 图1 12个零件按珠子数分3大类: 第1大类,有三个珠子,只有一种形状. 符号为A,形状为 ...

  6. [NOI 2005]聪聪和可可

    Description 题库链接 一只猫和一只老鼠在一张 \(n\) 个节点和 \(m\) 条边的无向图上,初始位置不同.对于每一时刻,猫会先走,它走的方向为靠近老鼠的方向:若多个节点可选,则选字典序 ...

  7. BZOJ 1502 NOI 2005 月下柠檬树

    题目大意 给定一些圆和梯形,求它们面积的并 解答 直接用辛普森公式积分 ∫baf(x)×dx≈b−a6[f(a)+f(a+b2)+f(b)] \int_a^bf(x)\times dx \approx ...

  8. NOI 2009 题解

    变换序列 (传送门) 题意 对于0-N-1共N个整数,给一个距离序列D0-DN-1,定义一个变换序列T0-TN-1使得每个i,Ti的环上距离等于Di.一个合法的变换序列应是0-N-1的一个排列,任务是 ...

  9. NOI 2005 智慧珠游戏 zhzyx

    使劲搜索,判了一下连通块(大小<3则剪枝,3 <= 大小 <= 5 则填入对应的棋子,无法填入则剪枝),另外搜索之前判一下棋盘上半.下半部分空格的数量关系,若上面的空格较多,则把棋盘 ...

最新文章

  1. 阅读日志:协鑫一年的多晶硅料产能能够生产做少装机容量的组件?
  2. python经典排序_python实现十大经典排序算法
  3. 设计模式(Design Pattern)
  4. NOIP 2006 T2 金明的预算方案
  5. perl java_与Perl相比Java性能问题
  6. 基于android平台的24点游戏设计与实现需求分析,基于Android平台的24点游戏设计与实现需求分析_毕业设计论文.doc...
  7. 在python中传统除法运算符是_在Python中使用除法运算符时,如何获取十进制值?...
  8. python获取磁盘剩余空间的方法
  9. ActiveMQ常见操作
  10. Danfo.js专题 - Series对象
  11. 魔域手游安卓修改服务器地址,魔域手游服务端商业版
  12. 细胞自动机 通用计算机,科学网—《走近混沌》-27-初级细胞自动机 - 张天蓉的博文...
  13. smartdrv.exe是什么(收藏)
  14. freemarker英文日期显示成中文问题
  15. dlib重新训练dlib_face_recognition_resnet_model_v1.dat
  16. kaggle常见操作及错误
  17. 软件工程作业之甘特图
  18. Jetpack Compose中的手势操作
  19. Unity 获取鼠标点击图片时 获取点击位置的像素
  20. 峰值电流源微电流源分析

热门文章

  1. 无糖饮料难破“高端局”
  2. 一款开源的指纹识别SDK
  3. blackjack java gui_求助一个java的题,blackjack, class 分为Card 和Deck,求大神帮我做一个程序...
  4. html无序列表透明圆点,html无序列表的类型type
  5. Java 常见笔试题(转载)
  6. 浏览器提示ssl证书过期怎么办
  7. 东华大学计算机学院刘国华,东华大学计算机科学与技术学院研究生导师简介-刘国华??(教授)...
  8. draco压缩引擎学习笔记(一)
  9. 代码中的下划线_是什么意思呢?
  10. git restore指令和git restore --staged 的使用