第二题:bfs,忘了将queue清空。
第三题:bfs,记得使用vis数组,防止重复入队
第三题:bfs会MLE。DFS只需使用到long long的19位长度即可。
分析:
BFS显然会按照2^N增长;还没找到答案之前内存就爆炸了。
至于为什么可以用long long解决,不说前人探索出来的规律。你想想,如果是暴力搜索DFS,如果答案真得可能会到100位,那就会超出时间限制,所以位数不会太长。
但要是超过了19位呢?那就用结构体来模拟除法咯,不过还是要用DFS。
第四题:
处在简单搜索这个题目集里面真是刺激到我了,所以人有点浮躁。然后还打游戏,精神不好,出了很多错误。所以,认真对待,用最好的面貌去迎接挑战。
#include<cstdio> #include<cstdlib> #include<cstring> #define maxn 25 #define sc scanf #define pt printf #define rep(i,a,b) for(int i=a;i<b;++i) int a[maxn][maxn],op[maxn][maxn],out[maxn][maxn]; int m,n,cnt,ans; --op的核心是如果上面的位置是黑色,那么他就应该是为1. --但是,很简单的话语,包含了这个意思: 你可以省去了对a源数组的临时复制,只需要考虑周边产生的操作以及原位置的数值即可得到当前的op值 int main() { #ifdef WANGNINGLOCAL freopen("in.txt","r",stdin); #endif --这个是没有必要的,因为全局数组声明的时候未初始化,自动填充0. --而且,根本不会用到出界的a数组。 --所以是逼急了的情况下抓的无用的稻草。 memset(a,0,sizeof(a)); while(~sc("%d%d",&n,&m)) { ans=0x3f3f3f3f; rep(i,1,n+1) rep(j,1,m+1) sc("%d",&a[i][j]); rep(b,0,1<<m) { //pt("当前用于分解的二进制对象是 %d ",b); memset(op,0,sizeof(op)); cnt=0; for(int i=m;i>=1;--i) { --考虑到字典序最小,所以将从右往左赋最低到最高位。 op[1][i] = (b>>(m-i))&1; //pt("在填第%d位,内容是%d ",i,op[1][i]); cnt += op[1][i]; } rep(i,2,n+1) { rep(j,1,m+1) { int jg = a[i-1][j] + op[i-1][j] + op[i-1][j-1] + op[i-1][j+1]; if(i>=3) jg+=op[i-2][j]; if(jg%2==1) { op[i][j]=1; --这里是一个大错误,之前把上面的代码复制下来,那实际上完全就不应该用op[1][i]来在这里累加cnt cnt += op[i][j]; } } } int i; for(i=1;i<=m;++i) { int jg = a[n][i] + op[n][i] + op[n][i-1] + op[n][i+1] +op[n-1][i]; if(jg%2==1) break; } if(i==m+1) { if(cnt<ans) { ans=cnt; memcpy(out,op,sizeof(op)); } } } if(ans==0x3f3f3f3f) pt("IMPOSSIBLE "); else { --这里都是错误,因为之前没有写else语句。 rep(i,1,n+1) rep(j,1,m+1) pt("%d%c",out[i][j]," "[j==m]); } } return 0; }
回过头来修改的自己最初的代码版本,里面居然纠正出了五个错误
#include<cstdio> #include<cstdlib> #include<cmath> #include<map> #include<queue> #include<set> #include<vector> #include<cctype> #include<algorithm> #include<cstring> #include<iostream> using namespace std; #define sc scanf #define pt printf #define pi acos(-1.0) #define inf 0x3f3f3f3f #define maxn 25 #define rep(i,a,b) for(int i=a;i<b;++i) #define ull unsigned long long #define pb push_back int R,C,i,j,x,k,mi,who,now; int mp[maxn][maxn]; int cp[maxn][maxn]; int main() { --大致思路:对cp二维数组进行实际的值的修改来模拟过程 --第一行是要直接复制mp的内容的,接下来的R-1行会在动态修改的过程中逐行调用mp源数组的值 --接下来会说说自己主要错在哪 #ifdef WANGNINGLOCAL freopen("in.txt","r",stdin); #endif while(~scanf("%d%d",&R,&C)) { for(i=1;i<=R;++i) for(j=1;j<=C;++j) sc("%d",&mp[i][j]); mi=inf; who=-1; for(i=0;i<1<<C;++i) { //pt("i=%d!!! ",i); now=0; x=i; for(j=1;j<=C;++j) cp[1][j] = mp[1][j]; for(j=C;j>=1;--j) { cp[1][j]=(x&1)^cp[1][j]; cp[1][j+1]=(x&1)^cp[1][j+1]; cp[1][j-1]=(x&1)^cp[1][j-1]; cp[2][j]=(x&1)^mp[2][j]; now+=(x&1); x=x>>1; } //你要搞懂,cp存的是什么 //第一行放的是修改后的值,第二行及以后放的是修改后的值 for(j=2;j<=R;++j) { for(k=1;k<=C;++k) { //pt("%d%c",cp[j-1][k]," "[k==C]); if(cp[j-1][k]==1) { ++now; cp[j][k]=!cp[j][k]; cp[j][k-1]=!cp[j][k-1]; cp[j][k+1]=!cp[j][k+1]; cp[j+1][k]=!mp[j+1][k]; } else cp[j+1][k]=mp[j+1][k]; } } //判断依据是如果所有的操作都完毕后,最后一行如果有1值出现,那么方案不成立 for(j=1;j<=C;++j) { //pt("%d%c",cp[R][j]," "[j==C]); if(cp[R][j]==1) break; } if(j==C+1) { if(now<mi) { mi=now; who=i; } } } if(who==-1) pt("IMPOSSIBLE "); else { //pt("%d %d ",who,mi); for(j=1;j<=C;++j) cp[1][j] = mp[1][j]; //for(k=1;k<=C;++k) pt("%d%c",cp[1][k]," "[k==C]); --错误点1:输出顺序必有先后,但是我从末位开始取值输出就错了。 --错误点2:j还是从C到1,但是第一位取出来的异或值用在了最后一位上,第二位用在了倒数第二位上 也就是说输出顺序与操作顺序反了 --错误点3:异或值整体是(who>>(C-j))&1,但是下面用成了who>>(C-j),可能以为右移了就只剩下那一位了吧 for(j=1;j<=C;++j) { pt("%d%c", ( who>>(C-j) )&1," "[j==C]); cp[1][j]=( ( who>>(C-j) )&1 )^cp[1][j]; cp[1][j+1]=( ( who>>(C-j) )&1 )^cp[1][j+1]; cp[1][j-1]=( ( who>>(C-j) )&1 )^cp[1][j-1]; cp[2][j]=( ( who>>(C-j) )&1 )^mp[2][j]; } //for(k=1;k<=C;++k) pt("%d%c",cp[1][k]," "[k==C]); for(j=2;j<=R;++j) { for(k=1;k<=C;++k) { if(cp[j-1][k]==1) { pt("%d%c",1," "[k==C]); cp[j-1][k]=0; cp[j][k]=!cp[j][k]; cp[j][k-1]=!cp[j][k-1]; cp[j][k+1]=!cp[j][k+1]; cp[j+1][k]=!mp[j+1][k]; } --错误点5:没有执行cp[j+1][k]=mp[j+1][k]操作 else { cp[j+1][k]=mp[j+1][k]; pt("%d%c",0," "[k==C]); } } } } } return 0; }
第五题: 使用了BFS,思路是先找出1000~9999之间的质数,然后对每个这样的质数寻找变动一位后的所有数,用map<int, vector<int> > nei 记录下来
之后对每个输入的起点数,只要用结构体
typedef struct nod{
int what,dis;
}nod;
what代表到了哪个数,dis表示走了几步,使用BFS就行了。
注意点:
1.仍旧是queue的清空问题——虽然这回我是没有在上面犯错的,但依旧觉得很重要。
2.vis数组使用了,时间在0.3秒; 没用使用,时间在2.4秒。 —— 仅从样例来看。
所以,走过的路,已经有人走过了,就不用再走,不论前方是成功还是失败,成功了果实不是你的,因为你的dis比别人的大,也就是来得晚了;
别人如果失败了,那你干嘛要走呢?另寻他途吧。
#include<cstdio> #include<cstdlib> #include<cmath> #include<map> #include<queue> #include<set> #include<vector> #include<cctype> #include<algorithm> #include<cstring> #include<iostream> using namespace std; #define sc scanf #define pt printf #define pi acos(-1.0) #define inf 0x3f3f3f3f #define maxn 10005 #define rep(i,a,b) for(int i=a;i<b;++i) #define ull unsigned long long #define pb push_back #define ull unsigned long long int vis[maxn]; int isprime[maxn]; vector<int> pri; map<int, vector<int> > nei; typedef struct nod{ int what,dis; }nod; queue<nod> q; nod ob,now; int mypow(int a,int b) { int ret = 1; rep(i,0,b) ret*=a; return ret; } void findnei(int who,int ra) //ra是倒数第几位 { int i,j,k,x; int sum=0,po; for(i=3;i>=0;--i) //i=2时,是百位,但是是倒数第三位。 { if(i==ra-1) continue; sum+=mypow(10,i)*(who/mypow(10,i)%10); } for(i=0;i<=9;++i) { x=sum+i*mypow(10,ra-1); if(x!=who&&isprime[x]==0) nei[who].pb(x); } } int main() { #ifdef WANGNINGLOCAL freopen("in.txt","r",stdin); //freopen("out.txt","w",stdout); #endif memset(isprime,0,sizeof(isprime)); // --1 不是prime int T,n,m,i,j,k,x,y,z,cnt; /*获取质数*/ for(i=2;i<maxn;++i) { if(isprime[i]==0) { if(i>=1000&&i<=9999) pri.pb(i); //只要四位数字级别的 for(j=i*i;j<maxn;j+=i) isprime[j]=1; } } /*下面将只相差一位且为质数的数字压入*/ for(i=0;i<(int)pri.size();++i) { //千位不同 x=pri[i]; y=x%1000; for(j=1;j<=9;++j) { z=j*1000+y; if(isprime[z]==0 && z!= x) nei[x].pb(z); } //百位不同 for(j=1;j<=3;++j) findnei(x,j); } sc("%d",&T); while(T--) { sc("%d%d",&n,&m); while(!q.empty()) q.pop(); memset(vis,0,sizeof(vis)); vis[n]=1; cnt=0; ob.dis=0; ob.what=n; q.push(ob); while(!q.empty()) { now=q.front(); q.pop(); if(now.what==m) break; ob.dis=now.dis+1; rep(i,0,(int)nei[now.what].size()) { z= nei[now.what][i]; if(!vis[z]) { ob.what = z; vis[z]=1; q.push(ob); } } } if(now.what==m) pt("%d ",now.dis); else pt("Impossible "); } return 0; } /* //看看对不对 对的 for(i=0;i<(int)pri.size();++i) { //千位不同 x=pri[i]; pt("x=%d ",x); for(j=0;j<(int)nei[x].size();++j) { pt(":) %d%c ",nei[x][j]," "[j==(int)nei[x].size()-1]); } //百位不同 for(j=1;j<=3;++j) findnei(x,j); } */
第六题:数组大小开错了,要注意合并的长度会达到2*C。
#include<cstdio> #include<cstring> #include<set> #include<cstring> #include<iostream> using namespace std; #define sc scanf #define pt printf #define maxn 105 int main() { set<string> s; #ifdef WANGNINGLOCAL freopen("in.txt","r",stdin); #endif int T,len,i,run=0,cnt; string ob; char a[maxn],b[maxn],tar[2*maxn],cp[2*maxn]; sc("%d",&T); while(T--) { for(i=0;i<maxn;++i) a[i]=b[i]=tar[i]=cp[i]='