虫食算
来源:互联网 发布:中国心力衰竭数据平台 编辑:程序博客网 时间:2024/05/20 11:24
这是一道很好的题目,教给了我很多暴力的剪枝方法
超链接不解释。。。。
https://www.luogu.org/problem/show?pid=1092
解释:
重构了两遍代码才A掉的,当时思路真的有问题,没办法剪枝和处理进位情况,读了一个题解描述。
好了正题
整体思路是从后向前,从上向下的依次搜索三个大数据
几个相当重要且有趣的剪枝+思路:
1.每次搜完就判断是否已经有不合法情况出现:一列三个已知不合法,例如1+1=3;已知两个数未知进位 但 进不进 都不可以满足就不合法;一列已知两个数以及进位计算后不合法。这三种情况直接return
2.重新整理一遍进位
3.在搜一个数时如果所有情况都失败则return;
4.一列已知两个数及进位情况就直接算第三个数 !!且不满足时直接return!!
5.如果不满足3.4,孩子老老实实搜吧,但是从后面往前搜会快哦
#include <cstdio>#include <iostream>#include <cstring>using namespace std;bool ff=false,d[30];int map[4][30],jw[30];int n,r[30];bool pd(){int add=0,i;for (i=n;i>=1;i--){if (r[map[1][i]]!=-1 && r[map[2][i]]!=-1 && r[map[3][i]]!=-1) { if (add==-1 && (r[map[1][i]]+r[map[2][i]])%n!=r[map[3][i]] && (r[map[1][i]]+r[map[2][i]]+1)%n!=r[map[3][i]])//没有已知进位 return false; if (add!=-1) if ((r[map[1][i]]+r[map[2][i]]+add)%n!=r[map[3][i]]) return false;//有已知进位 else add=(r[map[1][i]]+r[map[2][i]]+add)/n;}else add=-1;}return true;}int find(int i,int j)//有没有知二求三 或者是 直接不合法 {if(j==1){if (r[map[2][i]]!=-1 && r[map[3][i]]!=-1) { int quq=(r[map[3][i]]-r[map[2][i]]+n)%n; if(jw[i+1]==1) quq=(quq-1+n)%n; if (d[quq]) return -2; else return quq; }return -1;}else if (j==2) { if (r[map[1][i]]!=-1 && r[map[3][i]]!=-1) { int quq=(r[map[3][i]]-r[map[1][i]]+n)%n; if(jw[i+1]==1) quq=(quq-1+n)%n; if (d[quq]) return -2; else return quq; }return -1; }else { if (r[map[1][i]]!=-1 && r[map[2][i]]!=-1) { int quq=(r[map[2][i]]+r[map[1][i]])%n;if(jw[i+1]==1) quq=(quq+1)%n; if (d[quq]) return -2; else return quq; }return -1; }}void gx()//重新整理进位 {int i;for (i=n;i>=1;i--)if (r[map[1][i]]!=-1 && r[map[2][i]]!=-1 && jw[i+1]!=-1) if (r[map[1][i]]+r[map[2][i]]+jw[i+1]>=n) jw[i]=1; else jw[i]=0;else return;}void dfs(int t,int x){if (ff) return;int i,j,k;if (!pd()) return;gx();if (t==0){ff=true;for (i=1;i<=n-1;i++)printf("%d ",r[i]);printf("%d ",r[i]);return;}for (k=x;k>=1;k--)for (j=1;j<=3;j++) if (r[map[j][k]]==-1){int tmp=find(k,j);if (tmp==-1){for (i=0;i<=n-1;i++) if (!d[i] && !ff) { d[i]=true; r[map[j][k]]=i; dfs(t-1,k); d[i]=false; r[map[j][k]]=-1; } return;}else if (tmp==-2) return;else{d[tmp]=true;r[map[j][k]]=tmp;dfs(t-1,k);d[tmp]=false;r[map[j][k]]=-1;return;}}}int main(){ int j;char l;scanf("%d\n",&n);for (j=1;j<=n;j++){scanf("%c",&l); map[1][j]=l-'A'+1;} scanf("%d\n");for (j=1;j<=n;j++){scanf("%c",&l); map[2][j]=l-'A'+1;}scanf("%d\n");for (j=1;j<=n;j++){scanf("%c",&l); map[3][j]=l-'A'+1;}memset(d,0,sizeof(d));memset(r,-1,sizeof(r));memset(jw,-1,sizeof(jw));jw[n+1]=0;dfs(n,n);}
0 0
- 虫食算
- 虫食算
- 虫食算
- 虫食算
- 虫食算
- 虫食算
- 虫食算
- 虫食算
- 虫食算
- 虫食算
- noip 虫食算
- Noip2004T4 虫食算
- NOIP2004虫食算
- NOIP2004 虫食算
- 【NOIP2004】虫食算
- NOIP2004【虫食算】
- 搜索--虫食算
- 【高斯消元】虫食算
- CI框架
- [LeetCode]413. Arithmetic Slices
- 如何理解和熟练运用js中的call及apply
- 深度学习Caffe实战笔记(2)用LeNet跑车牌识别数据
- jquery多选择动态参数的使用以及ajax异步请求中提交整个form表单中serializeArray()的使用以及后台值得获取方式
- 虫食算
- 程序员的七大痛点
- git命令
- 关于Fragment和Activity之间通讯传参的一点小心得
- Git常用命令及使用心得
- 银行卡号验证js(luhn算法)
- Android Linux内核驱动程序(基于mtk方案 3.18内核)
- Linux 文件按大小排序
- 梯形概率分布