挑战编程程序设计 搜索练习
8.6.1棋盘上的象
题目大意:在n*n的棋盘上放象,每个象的对角线上不能有别的象,求总共的方案数。
思路:搜索,肯定超时。dp~~排列组合~~又不会,只能打表了,好凶残。直接a(放0头象竟然是1种方案)。
#include<iostream> #include<cstdio> #include<cstring> using namespace std; int d1[20]={0},d2[20]={0},n,k; long long ans; void work(int i,int j,int di) { int dd1,dd2,yu; if (di>k) { ++ans; return; } if (i>n||j>n) return; yu=(n-i)*n+n-j+1; if (yu<k-di+1) return; dd1=i-j+8;dd2=i+j; if (d1[dd1]==0&&d2[dd2]==0) { ++d1[dd1];++d2[dd2]; if (j==n) work(i+1,1,di+1); else work(i,j+1,di+1); --d1[dd1];--d2[dd2]; } if (j==n) work(i+1,1,di); else work(i,j+1,di); } int main() { while(scanf("%d%d",&n,&k)==2) { if (n==0&&k==0) break; ans=0; memset(d1,0,sizeof(d1)); memset(d2,0,sizeof(d2)); work(1,1,1); printf("%lld ",ans); } }
#include<iostream> #include<cstdio> using namespace std; long long biao[9][65]={0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,4,4,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,9,26,26,8,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,16,92,232,260,112,16,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,25,240,1124,2728,3368,1960,440,32,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,36,520,3896,16428,39680,53744,38368,12944,1600,64,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,49,994,10894,70792,282248,692320,1022320,867328,389312,81184,5792,128,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,64,1736,26192,242856,1444928,5599888,14082528,22522960,22057472,12448832,3672448,489536,20224,256,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}; int main() { int n,k; while(scanf("%d%d",&n,&k)==2) { if (n==0&&k==0) break; printf("%lld ",biao[n][k]); } }
8.6.2十五数码
题目大意:常见的十五数码问题,输出步骤(不一定是最优解)
思路:借这个题学习了一下a*算法,最关键的估价函数(这个题中,也能重视到估价函数的重要性,这个题目f(n)=g(n)+4/3h(n),话说为什么要4/3?只是实践?不加4/3就a不了),顺带练习了map和优先队列。其实a*算法,比较好理解,一个open优先队列,一个close map关系,对于每个优先队列中得分最低的元素进行处理,加入close、四个方向,然后将拓展到的判断是否已经出现在close中,若出现,就从close中把原来的删掉(原来的步数多的情况下),然后加入到open中。重复上述操作直到找到答案或者open为空。最后就是输出步骤了,当然,这道题中还要先判断是否有解,再做,否则会超时的。。。
#include<iostream> #include<cstdio> #include<algorithm> #include<cstring> #include<queue> #include<cmath> #include<map> using namespace std; struct use{ int num[16],kg,stt,st[100],score; long long cant; }a; bool operator<(use x,use y) { return x.score>y.score; } long long jie[16]={0}; int move[4]={0},wy[4]={-1,1,-4,4},manha[16][16]={0}; bool noans(struct use xx) { int ge=0,i,j; for (i=0;i<15;++i) for (j=i+1;j<=15;++j) if (xx.num[i]<xx.num[j]&&(xx.num[i]!=0)) ++ge; ge+=(xx.kg/4)+1; if (ge%2==0) return true; else return false; } void manh() { int i,j,x1,x2,y1,y2; for (i=0;i<16;++i) for (j=0;j<16;++j) { x1=i%4;y1=i/4; x2=j%4;y2=j/4; manha[i][j]=(abs(x1-x2)+abs(y1-y2)); } } long long cantor(struct use xx) { int i,j,ge=0; long long ans; for (i=0;i<=14;++i) { ge=0; for (j=i+1;j<=15;++j) if (xx.num[i]>xx.num[j]) ++ge; ans+=jie[15-i]*ge; } return ans; } int sco(struct use xx,int dep) { int i,j,ans,x1,y1,x2,y2; ans=0; for (i=0;i<=15;++i) ans+=manha[i][(xx.num[i]+15)%16]; return dep+(4*ans/3); } bool comp(struct use xx) { int i; if (xx.num[15]!=0) return false; for (i=0;i<15;++i) if (xx.num[i]!=i+1) return false; return true; } void explore(struct use xx) { int i,j,x,la; move[0]=move[1]=move[2]=move[3]=-1; x=xx.kg;la=-1; if (xx.stt>0) la=xx.st[xx.stt]; if (x%4>0&&la!=1) move[0]=0; if (x%4<3&&la!=0) move[1]=1; if (x/4>0&&la!=3) move[2]=2; if (x/4<3&&la!=2) move[3]=3; } void print(struct use xx) { int i; for (i=1;i<=xx.stt;++i) { if (xx.st[i]==0) printf("L"); if (xx.st[i]==1) printf("R"); if (xx.st[i]==2) printf("U"); if (xx.st[i]==3) printf("D"); } printf(" "); } void work() { int i,j; struct use ne,th; a.score=sco(a,0); a.stt=0; a.cant=cantor(a); priority_queue < use > open; map < long long,int> close; open.push(a); while(!open.empty()) { th=open.top(); open.pop(); close.insert(make_pair< long long,int> (th.cant,th.score)); if (comp(th)) { print(th); return; } explore(th); for (i=0;i<4;++i) { if (move[i]==-1) continue; ne=th; ne.kg=th.kg+wy[i]; ne.num[th.kg]=ne.num[ne.kg];ne.num[ne.kg]=0; ne.stt=th.stt+1;ne.st[ne.stt]=i; if (ne.stt>50) continue; ne.cant=cantor(ne); ne.score=sco(ne,ne.stt); map < long long,int >::iterator it =close.find(ne.cant); if (it!=close.end()) { if (ne.score>=(*it).second) continue; close.erase(it); } open.push(ne); } } } int main() { int n,i,j,cci; manh(); jie[1]=1; for (i=2;i<=15;++i) jie[i]=jie[i-1]*i; scanf("%d",&n); for (cci=1;cci<=n;++cci) { for (i=0;i<16;++i) { scanf("%d",&a.num[i]); if (a.num[i]==0) a.kg=i; } if (comp(a)) printf(" "); else { if (noans(a)) printf("This puzzle is not solvable. "); else work(); } } }
8.6.3队伍
题目大意:n个人站队,恰有p个人比左边的人都高,恰有r个人比右边的人都高,求总的方案数。
思路:搜索,一开始是按位置搜的,超时妥妥的。之后改了搜索方法,从高的往小的放,如果当前的人放在已放过的左边;就相当于多了一个比左边人都高的,如果当前的人放在已放过的右边,就相当于多了一个比右边人都高的;如果放在之间的话,就没有变化。然后搜出来的相对要快,可是还是没法满足我们的要求,于是又用了打表,打了十分钟的表,终于a了。
#include<iostream> #include<cstdio> #include<cstring> using namespace std; int n; long long ans=0; bool use[14]={false}; void work(int i,int ll,int rr,int le,int re) { int j; if (i>n&&le==0&&re==0) { ++ans; return; } if (ll-1<le) return; if (n-rr<re) return; if (i==1) { for (j=le;j<=n-re+1;++j) { use[j]=true; work(i+1,j,j,le-1,re-1); use[j]=false; } } else { for (j=le;j<=n-re+1;++j) { if (j<1||j>n) continue; if (!use[j]) { use[j]=true; if (j<ll&&le>0) work(i+1,j,rr,le-1,re); if (j>ll&&j<rr) work(i+1,ll,rr,le,re); if (j>rr&&re>0) work(i+1,ll,j,le,re-1); use[j]=false; } } } } int main() { int i,j,ci,t,l,r; scanf("%d",&t); for (ci=1;ci<=t;++ci) { scanf("%d%d%d",&n,&l,&r); memset(use,false,sizeof(use)); ans=0; work(1,n+1,0,l,r); printf("%lld ",ans); } }
#include<iostream> #include<cstdio> using namespace std; long long ans[14][14][14]={0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,0,0,0,0,0,0,0,0,0,0,0,1,2,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,3,1,0,0,0,0,0,0,0,0,0,0,2,6,3,0,0,0,0,0,0,0,0,0,0,0,3,3,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,6,11,6,1,0,0,0,0,0,0,0,0,0,6,22,18,4,0,0,0,0,0,0,0,0,0,0,11,18,6,0,0,0,0,0,0,0,0,0,0,0,6,4,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,24,50,35,10,1,0,0,0,0,0,0,0,0,24,100,105,40,5,0,0,0,0,0,0,0,0,0,50,105,60,10,0,0,0,0,0,0,0,0,0,0,35,40,10,0,0,0,0,0,0,0,0,0,0,0,10,5,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,120,274,225,85,15,1,0,0,0,0,0,0,0,120,548,675,340,75,6,0,0,0,0,0,0,0,0,274,675,510,150,15,0,0,0,0,0,0,0,0,0,225,340,150,20,0,0,0,0,0,0,0,0,0,0,85,75,15,0,0,0,0,0,0,0,0,0,0,0,15,6,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,720,1764,1624,735,175,21,1,0,0,0,0,0,0,720,3528,4872,2940,875,126,7,0,0,0,0,0,0,0,1764,4872,4410,1750,315,21,0,0,0,0,0,0,0,0,1624,2940,1750,420,35,0,0,0,0,0,0,0,0,0,735,875,315,35,0,0,0,0,0,0,0,0,0,0,175,126,21,0,0,0,0,0,0,0,0,0,0,0,21,7,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,5040,13068,13132,6769,1960,322,28,1,0,0,0,0,0,5040,26136,39396,27076,9800,1932,196,8,0,0,0,0,0,0,13068,39396,40614,19600,4830,588,28,0,0,0,0,0,0,0,13132,27076,19600,6440,980,56,0,0,0,0,0,0,0,0,6769,9800,4830,980,70,0,0,0,0,0,0,0,0,0,1960,1932,588,56,0,0,0,0,0,0,0,0,0,0,322,196,28,0,0,0,0,0,0,0,0,0,0,0,28,8,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,40320,109584,118124,67284,22449,4536,546,36,1,0,0,0,0,40320,219168,354372,269136,112245,27216,3822,288,9,0,0,0,0,0,109584,354372,403704,224490,68040,11466,1008,36,0,0,0,0,0,0,118124,269136,224490,90720,19110,2016,84,0,0,0,0,0,0,0,67284,112245,68040,19110,2520,126,0,0,0,0,0,0,0,0,22449,27216,11466,2016,126,0,0,0,0,0,0,0,0,0,4536,3822,1008,84,0,0,0,0,0,0,0,0,0,0,546,288,36,0,0,0,0,0,0,0,0,0,0,0,36,9,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,362880,1026576,1172700,723680,269325,63273,9450,870,45,1,0,0,0,362880,2053152,3518100,2894720,1346625,379638,66150,6960,405,10,0,0,0,0,1026576,3518100,4342080,2693250,949095,198450,24360,1620,45,0,0,0,0,0,1172700,2894720,2693250,1265460,330750,48720,3780,120,0,0,0,0,0,0,723680,1346625,949095,330750,60900,5670,210,0,0,0,0,0,0,0,269325,379638,198450,48720,5670,252,0,0,0,0,0,0,0,0,63273,66150,24360,3780,210,0,0,0,0,0,0,0,0,0,9450,6960,1620,120,0,0,0,0,0,0,0,0,0,0,870,405,45,0,0,0,0,0,0,0,0,0,0,0,45,10,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,3628800,10628640,12753576,8409500,3416930,902055,157773,18150,1320,55,1,0,0,3628800,21257280,38260728,33638000,17084650,5412330,1104411,145200,11880,550,11,0,0,0,10628640,38260728,50457000,34169300,13530825,3313233,508200,47520,2475,55,0,0,0,0,12753576,33638000,34169300,18041100,5522055,1016400,110880,6600,165,0,0,0,0,0,8409500,17084650,13530825,5522055,1270500,166320,11550,330,0,0,0,0,0,0,3416930,5412330,3313233,1016400,166320,13860,462,0,0,0,0,0,0,0,902055,1104411,508200,110880,11550,462,0,0,0,0,0,0,0,0,157773,145200,47520,6600,330,0,0,0,0,0,0,0,0,0,18150,11880,2475,165,0,0,0,0,0,0,0,0,0,0,1320,550,55,0,0,0,0,0,0,0,0,0,0,0,55,11,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,39916800,120543840,150917976,105258076,45995730,13339535,2637558,357423,32670,1925,66,1,0,39916800,241087680,452753928,421032304,229978650,80037210,18462906,2859384,294030,19250,726,12,0,0,120543840,452753928,631548456,459957300,200093025,55388718,10007844,1176120,86625,3630,66,0,0,0,150917976,421032304,459957300,266790700,92314530,20015688,2744280,231000,10890,220,0,0,0,0,105258076,229978650,200093025,92314530,25019610,4116420,404250,21780,495,0,0,0,0,0,45995730,80037210,55388718,20015688,4116420,485100,30492,792,0,0,0,0,0,0,13339535,18462906,10007844,2744280,404250,30492,924,0,0,0,0,0,0,0,2637558,2859384,1176120,231000,21780,792,0,0,0,0,0,0,0,0,357423,294030,86625,10890,495,0,0,0,0,0,0,0,0,0,32670,19250,3630,220,0,0,0,0,0,0,0,0,0,0,1925,726,66,0,0,0,0,0,0,0,0,0,0,0,66,12,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0}; int main() { int ci,n,l,r; scanf("%d",&ci); while(ci) { scanf("%d%d%d",&n,&l,&r); printf("%lld ",ans[n][l][r]); --ci; } }
8.6.5拔河
题目大意:有n个人拔河,将这n个人尽量平分,使两队的人不相差多于1个,然后使两队的体重数相差尽量小,输出分配方案。
思路:之前做过这个题,用的是背包。用容积为总容积一半的背包,装一半的物品,然后用布尔数组保存这些,最后从一半容积处穷举,找到最优解就可以了。
#include<iostream> #include<cstdio> #include<cstring> using namespace std; bool f[101][45001]={false}; int a[101]={0}; int main() { int i,j,sum=0,n,k,q,cha,summ,ci; scanf("%d",&ci); while(ci) { cin>>n; sum=0; memset(f,false,sizeof(f)); if (n%2==0) k=n/2; else k=n/2+1; for (i=1;i<=n;++i) { cin>>a[i]; sum+=a[i]; } if (sum%2==0) summ=sum/2; else summ=sum/2+1; for (i=0;i<=n;++i) f[i][0]=true; for (i=1;i<=n;++i) for (j=summ;j>=a[i];--j) for (q=k;q>=1;--q) f[q][j]=f[q][j]||f[q-1][j-a[i]]; for (j=summ;j>=0;--j) if (f[k][j]) { cout<<min(j,sum-j)<<" "<<max(j,sum-j)<<endl; break; } if (ci>1) cout<<endl; --ci; } }
8.6.6伊甸园
题目大意:给定变化规则,然后判断给定状态有无前驱。
思路:理解题意用了好久。。。终于明白一个状态里面的每个元素都要同时发生变化。然后就是比较简单的搜索了(我的初始化太肮脏,本来循环就可以了,怪我不会位运算。。。)被这么一道题坑了好久,原来是while(scanf(“%d%d”,&n,&m)==2)忘了==2,一直T。。。
#include<iostream> #include<cstdio> using namespace std; int rule[8][4]={0},mo[34]={0},cc[34]={0},n,m; bool f=false; int tepan() { int i; if (m==0) { for (i=1;i<=n;++i) if (mo[i]!=0) return 0; return 1; } if (m==255) { for (i=1;i<=n;++i) if (mo[i]!=1) return 0; return 1; } return 2; } void rul() { if (m>=128) { rule[7][0]=rule[7][1]=rule[7][2]=rule[7][3]=1; m-=128; } else { rule[7][1]=rule[7][2]=rule[7][3]=1;rule[7][0]=0; } if (m>=64) { rule[6][0]=rule[6][1]=rule[6][2]=1;rule[6][3]=0; m-=64; } else { rule[6][1]=rule[6][2]=1;rule[6][0]=rule[6][3]=0; } if (m>=32) { rule[5][1]=rule[5][3]=rule[5][0]=1;rule[5][2]=0; m-=32; } else { rule[5][1]=rule[5][3]=1;rule[5][0]=rule[5][2]=0; } if (m>=16) { rule[4][1]=rule[4][0]=1;rule[4][2]=rule[4][3]=0; m-=16; } else { rule[4][1]=1;rule[4][0]=rule[4][2]=rule[4][3]=0; } if (m>=8) { rule[3][1]=0;rule[3][2]=rule[3][3]=rule[3][0]=1; m-=8; } else { rule[3][1]=rule[3][0]=0;rule[3][2]=rule[3][3]=1; } if (m>=4) { rule[2][1]=rule[2][3]=0;rule[2][2]=rule[2][0]=1; m-=4; } else { rule[2][1]=rule[2][3]=rule[2][0]=0;rule[2][2]=1; } if (m>=2) { rule[1][1]=rule[1][2]=0;rule[1][0]=rule[1][3]=1; m-=2; } else { rule[1][0]=rule[1][1]=rule[1][2]=0;rule[1][3]=1; } if (m>=1) { rule[0][0]=1;rule[0][1]=rule[0][2]=rule[0][3]=0; m-=1; } else { rule[0][0]=rule[0][1]=rule[0][2]=rule[0][3]=0; } } void work(int i) { int j,k; if (i>n) { if (cc[0]!=cc[n]) return; if (cc[1]!=cc[i]) return; f=true; return; } for (j=0;j<=7;++j) { if (rule[j][1]!=cc[i-1]) continue; if (rule[j][2]!=cc[i]) continue; if (rule[j][0]!=mo[i]) continue; cc[i+1]=rule[j][3]; work(i+1); if (f) return; } } int main() { int i,ff; char ch; while(scanf("%d%d",&m,&n)==2) { scanf("%*c"); for (i=1;i<=n;++i) { scanf("%c",&ch); mo[i]=ch-'0'; } ff=tepan(); if (ff==0) printf("GARDEN OF EDEN "); else { if (m==204||ff==1) printf("REACHABLE "); else { rul(); f=false; cc[0]=0;cc[1]=0; work(1); if (!f) { cc[0]=0;cc[1]=1; work(1); if (!f) { cc[0]=1;cc[1]=0; work(1); if (!f) { cc[0]=1;cc[1]=1; work(1); } } } if (f) printf("REACHABLE "); else printf("GARDEN OF EDEN "); } } } }