sgu 132 Another Chocolate Maniac
2016-03-11 22:55
274 查看
装压好题!
首先我们要从两个相邻的格子不能同时为空入手,然后我们不妨枚举每一行最后的状态,那下一行怎么办,我们还需要用一维来记录这一行的进位,也就是这一行用竖的格子放后的状态然后直接枚举即可,看起来像70*(3^14)的复杂度,其实我们对最终状态可以预处理,可以发现最多不超过21个,所以结论是dp[x][f]=dp[y][w]+count[f]+vis[x^f^s^w];
其中count数组记录的是当前二进制位数,vis记录横着放需要多少个,至于s是当前行candle的状态。
首先我们要从两个相邻的格子不能同时为空入手,然后我们不妨枚举每一行最后的状态,那下一行怎么办,我们还需要用一维来记录这一行的进位,也就是这一行用竖的格子放后的状态然后直接枚举即可,看起来像70*(3^14)的复杂度,其实我们对最终状态可以预处理,可以发现最多不超过21个,所以结论是dp[x][f]=dp[y][w]+count[f]+vis[x^f^s^w];
其中count数组记录的是当前二进制位数,vis记录横着放需要多少个,至于s是当前行candle的状态。
#include<cstdio> #include<cstring> #include<iostream> #include<algorithm> #include<vector> #define mp(a,b) make_pair(a,b) #define xx first #define yy second using namespace std; typedef long long LL; const int inf=1000000000; int dp[2][128][128],dp1[128][128]; char c[105][105]; int vis[128]; int cc[128]; vector<int>g; vector<int>g1[128]; int main() { int i,j,u,n,m; cin>>n>>m; for(i=1;i<=n;i++){ scanf("%s",c[i]); for(j=m;j>=1;j--) c[i][j]=c[i][j-1]; } u=0; int p=1<<m; for(i=0;i<p;i++){ vis[i]=inf; } for(i=1;i<p;i++){ cc[i]=cc[i^(i^(i&(i-1)))]+1; } vis[0]=0; for(i=1;i<p;i++){ int w=i&(i-1); w=i^w; if((i&(w<<1))==0) continue; vis[i]=vis[i^w^(w<<1)]+1; } for(i=0;i<p;i++){ for(j=0;j<p;j++){ if((i|j)==i){ g1[i].push_back(j); } } } for(j=0;j<p;j++){ int q=(p-1)^j; int w=((p-1)^j)<<1; if((q&w)!=0) continue; g.push_back(j); } for(i=0;i<p;i++){ for(j=0;j<p;j++){ dp[u][i][j]=1000000000; } } dp[u][p-1][0]=0; for(i=1;i<=n;i++){ u=u^1; int s=0; for(j=m;j>=1;j--){ s=s<<1; if(c[i][j]=='*'){ s+=1; } } for(j=0;j<p;j++){ int q=g1[j].size(); for(int f=0;f<q;f++){ dp1[j][g1[j][f]]=inf; } } int q=g.size(); for (j=0;j<q;j++) { int v=g[j]; int w=g1[v].size(); for(int f=0;f<w;f++){ if(dp[u^1][v][g1[v][f]]!=inf&&(g1[v][f]&s)==0){ for(int y1=0;y1<q;y1++){ int x=g[y1]; if((x|(g1[v][f]|s))!=x) continue; if((((p-1)^v)&((p-1)^x))!=0) continue; int p1=x^((g1[v][f]|s)); int ww=g1[p1].size(); for(int y=0;y<ww;y++){ dp1[x][g1[p1][y]]=min(dp1[x][g1[p1][y]],dp[u^1][v][g1[v][f]]+vis[p1^g1[p1][y]]+cc[g1[p1][y]]); } } } } } for(j=0;j<p;j++){ int q=g1[j].size(); for(int f=0;f<q;f++){ dp[u][j][g1[j][f]]=dp1[j][g1[j][f]]; } } } p=g.size(); int s=inf; for(i=0;i<p;i++){ s=min(s,dp[u][g[i]][0]); } cout<<s<<endl; }
相关文章推荐
- 栈应用之使用逆波兰输入求表达式的值
- Linux 字符设备驱动开发基础(四)—— ioctl() 函数解析
- NGINX server配置中if的用法
- 0311软件工程复利软件单利及期望值的实现
- 第二次作业 随机数四则运算
- 原生Javascript封装的一些常用函数
- linux的mount(挂载)命令详解
- 在adb中给android文件开通所有权限
- 不使用中间变量交换a,b值
- VS2012 + EF6.x + MySql 开发环境搭建问题 --- 终结篇
- jenkins配置.net mvc网站
- 关于内存申请的建议
- centos svnversion安装部署
- Android view手势拖动和缩放
- 软件工程课的个人理解
- 3月11日 异常语句 类
- 验证码
- 关于iOS自定义控件:在view上实现事件和代理
- Xcode开发的常见问题与解决方案
- iOS开发基础 :UIButton属性