生日礼物
#include<cstdio> int a[11][11],b[11],n,m; int ans[11],cnt=1001,t[11]; int is_ok(){ int s=0,t=0; for(int j=0;j<m;j++){ t=0; for(int i=0;i<n;i++){ t+=a[i][j]*ans[i]; } if(j==0)s=t; else if(s!=t)return 0; } return m*s; } int st(int k){ int s=0; for(int j=0;j<m;j++){ t[j]=0; for(int i=0;i<=k;i++) t[j]+=a[i][j]*ans[i]; s+=t[j]; if(s>=cnt)return 0; } for(int j=0;j<m;j++){ s=t[j]; for(int i=k;i<n;i++) s+=a[i][j]*b[i]; for(int i=0;i<m;i++){ if(i==j)continue; if(s<t[i])return 0; } } return 1; } void dfs(int k){ if(k==n){ int ok=is_ok(); if(ok)cnt=((cnt<ok)?cnt:ok); return ; } for(int i=0;i<=b[k];i++){ ans[k]=i; if(st(k)==0)return ; dfs(k+1); } } int main(){ scanf("%d%d",&n,&m); for(int i=0;i<n;i++) for(int j=0;j<m;j++) scanf("%d",&a[i][j]); for(int i=0;i<n;i++)scanf("%d",b+i); dfs(0); if(cnt>1000)printf("alternative!\n"); else printf("%d\n",cnt); return 0; } /* 剪枝: 1. 当前决策已经无法最优 2. 当前决策无法求出新解(各个颜色数目相等) */
#include<cstdio> #include<cstring> char prime[35],vis[20]; int n,a[20]; void _prime(){ memset(prime,1,sizeof(prime)); prime[0]=prime[1]=0; for(int i=2;i<35;i++)if(prime[i]){ for(int j=i+i;j<35;j+=i)prime[j]=0; } } void dfs(int k){ if(k==n){ if(prime[a[k-1]+a[0]]) for(int i=0;i<n;i++) printf(i<n-1?"%d ":"%d\n",a[i]); return ; } for(int i=2;i<=n;i++)if(!vis[i]){ vis[i]=1; a[k]=i; if(prime[a[k]+a[k-1]])dfs(k+1); vis[i]=0; } } int main(){ _prime(); scanf("%d",&n); a[0]=1; dfs(1); return 0; } /* 往结果集添加数据,边加边剪,暴力回溯 */
棋盘染色
#include<cstdio> #include<cstring> char g[10][10],vis[10][10]; int cnt,ans=26,ap,bx,by; struct Write{ int x,y; }a[40]; char v[10][10]; void _link(int i,int j,int&now){ if(i<1||i>5||j<1||j>5||v[i][j]||(!g[i][j]&&!vis[i][j])) return ; v[i][j]=1; if(g[i][j])now++; _link(i-1,j,now); _link(i+1,j,now); _link(i,j-1,now); _link(i,j+1,now); } void dfs(int k,int col){ if(col>=ans)return; if(k==ap){ int t=0; memset(v,0,sizeof(v)); _link(bx,by,t); if(t+ap==25)ans=col; return ; } vis[a[k].x][a[k].y]=0; dfs(k+1,col); vis[a[k].x][a[k].y]=1; dfs(k+1,col+1); vis[a[k].x][a[k].y]=0; } int main(){ for(int i=1;i<=5;i++){ scanf("%s",g[i]+1); for(int j=1;j<=5;j++){ g[i][j]-='0'; if(g[i][j]){cnt++;bx=i;by=j;} if(!g[i][j]){ a[ap].x=i; a[ap].y=j; ap++; } } } dfs(0,0); printf("%d\n",ans); return 0; } /* 记录下每个白色格子的位置,每个位置都有0/1的选择:表示染色或不染,不剪枝就是x层的二叉树,x是白色格子数目 */