【DP】coderforces 567F
2015-08-07 16:14
405 查看
正式开始刷cf的题。。。
cf的题真是厉害,随便找一道都这么变态,
真的是做过最麻烦的DP了。。。
状态很好想
f[i][j][k]表示从前往后填了i个从后往前填了j个最大数为k的概率。
然后就是暴力枚举每一个限制条件然后看能否转移。
就是暴力的话需要分类分的很清楚。
对于相等的情况,如果当前要转移状态一个被限制,而另一个没有限制,那么说明是不能转移的
对于大于的情况,如果当前要转移状态一个被限制,而限制条件的另一个位置还没填数,那么也不转移
对于大于等于的情况,如果当前转移状态一个被限制,而另一个位置也被限制,那么就是可以的,比大于多这么一条
至于小于和小于等于转换成大于和大于等于做就好了,
cf的题真是厉害,随便找一道都这么变态,
真的是做过最麻烦的DP了。。。
状态很好想
f[i][j][k]表示从前往后填了i个从后往前填了j个最大数为k的概率。
然后就是暴力枚举每一个限制条件然后看能否转移。
就是暴力的话需要分类分的很清楚。
对于相等的情况,如果当前要转移状态一个被限制,而另一个没有限制,那么说明是不能转移的
对于大于的情况,如果当前要转移状态一个被限制,而限制条件的另一个位置还没填数,那么也不转移
对于大于等于的情况,如果当前转移状态一个被限制,而另一个位置也被限制,那么就是可以的,比大于多这么一条
至于小于和小于等于转换成大于和大于等于做就好了,
#include<iostream> #include<cstring> #include<cmath> #include<cstdlib> #include<algorithm> #include<cstdio> using namespace std; bool flag1,flag2,flag3; long long f[110][110][41]; bool flag; long long ans; int m,n; struct rec { int x,y,biao; char s[10]; }lim[210]; bool ok(int l,int r,int x,int y) { for (int i=1;i<=m;i++) { if (lim[i].x==lim[i].y) continue; if (!strcmp(lim[i].s,"=")&&lim[i].x==x&&lim[i].y!=y) return false; if (!strcmp(lim[i].s,"=")&&lim[i].x==y&&lim[i].y!=x) return false; if (!strcmp(lim[i].s,"=")&&lim[i].x!=y&&lim[i].y==x) return false; if (!strcmp(lim[i].s,"=")&&lim[i].x!=x&&lim[i].y==y) return false; if (!strcmp(lim[i].s,">")&&lim[i].x==x&&lim[i].y<=r&&lim[i].y>=l) return false; if (!strcmp(lim[i].s,">")&&lim[i].x==y&&lim[i].y<=r&&lim[i].y>=l) return false; /* if (!strcmp(lim[i].s,">")&&lim[i].y==y&&lim[i].x<=r&&lim[i].x>=l) return false; if (!strcmp(lim[i].s,">")&&lim[i].y==x&&lim[i].x<=r&&lim[i].x>=l) return false;*/ if (!strcmp(lim[i].s,">=")&&lim[i].x==x&&lim[i].y<=r&&lim[i].y>=l&&lim[i].y!=y) return false; if (!strcmp(lim[i].s,">=")&&lim[i].x==y&&lim[i].y<=r&&lim[i].y>=l&&lim[i].y!=x) return false; /*if (!strcmp(lim[i].s,">=")&&lim[i].y==y&&lim[i].x<=r&&lim[i].x>=l&&lim[i].x!=x) return false; if (!strcmp(lim[i].s,">=")&&lim[i].y==x&&lim[i].x<=r&&lim[i].x>=l&&lim[i].x!=y) return false;*/ } return true; } int main() { freopen("test.in","r",stdin); freopen("test.out","w",stdout); memset(f,0,sizeof(f)); scanf("%d%d",&n,&m); f[1][2*n][0]=1; for (int i=1;i<=m;i++) { scanf("%d ",&lim[i].x); scanf("%s",lim[i].s); scanf("%d",&lim[i].y); if (!strcmp(lim[i].s,"<=")) { swap(lim[i].x,lim[i].y); lim[i].s[0]='>';lim[i].s[1]='='; } if (!strcmp(lim[i].s,"<")) { swap(lim[i].x,lim[i].y); lim[i].s[0]='>'; } } for (int k=1;k<=n;k++) for (int i=1;i<=2*n;i++) for (int j=2*n;j>=i;j--) if (f[i][j][k-1]) { //printf("f[%d][%d][%d]=%d\n",i,j,k-1,f[i][j][k-1]); if (ok(i,j,i,j)) f[i+1][j-1][k]+=f[i][j][k-1]; if (ok(i,j,i,i+1)) f[i+2][j][k]+=f[i][j][k-1]; if (ok(i,j,j-1,j)) f[i][j-2][k]+=f[i][j][k-1]; } for (int i=1;i<=2*n;i++) { flag=true; for (int j=1;j<=m;j++) { if (lim[j].x!=i&&lim[j].x!=i+1&&(lim[j].y==i||lim[j].y==i+1)) { flag=false; break; } if (lim[j].x==i&&lim[j].y==i+1&&(!strcmp(lim[j].s,">"))) { flag=false; break; } if (lim[j].x==i+1&&lim[j].y==i&&(!strcmp(lim[j].s,">"))) { flag=false; break; } } if (flag) ans+=f[i][i+1][n-1]; } for (int i=1;i<=m;i++) if (lim[i].x==lim[i].y&&(!strcmp(lim[i].s,">"))) ans=0; printf("%I64d",ans); return 0; }
相关文章推荐
- Ajax加载html部分内容到指定的标签内
- javascript对象拷贝
- Android 单元测试链接整理
- 把一个有规律的字符串分成一句话,首字母大写其他小写
- sso
- HTTP Header 详解
- 最小生成树之算法记录【prime算法+Kruskal算法】【模板】
- android studio 怎么调整字体
- poj2406 power strings 【KMP】
- 从C调用Lua
- JDK安装
- 游戏最高渲染帧率的垂直同步方式-----显示器的垂直刷新率
- 最小生成树之算法记录【prime算法+Kruskal算法】【模板】
- 异步时钟的同步化,俗称“慢打一拍",寄存一拍
- arpwatch
- java 多线程读取多个文件 和 不用线程读取多个文件
- Cause: java.sql.SQLException: Bad format for Time '308:42:13' in column
- HttpContext.Current.User.Identity.Name获得不了登录名
- 通过mmap函数快速实现文件复制
- hdu 5358 First One (2015多校第六场第6题)尺取法枚举区间和