[关闭]
@ysner 2018-05-08T12:53:06.000000Z 字数 3834 阅读 1888

拼字游戏

高斯消元 搜索


题面

有一个未知的的拼盘,它的每个元素都是正整数。给出行元素的总和,列元素的总和以及两条对角线元素总和。另外还给出了拼盘中任意个位置的元素值,它们的位置在输入文件中给定。
编写一个程序求出拼盘中另外个位置的正整数的值,要求这些元素的行之和,列
之和以及对角线之和与输入文件中给定的值相一致。
输一种方案即可

解析

算法

经过手动推算,如果数字的位置得当(比如有很多数在中间四格或四角),我们发现弄出个数就一定能解出整个矩阵。
于是我想到了暴枚个数,摆在适当的位置,再去推。
但可能存在解到一半就(表已知数,表未知数)


那么在空白地方随便摆个即可。
如果面向数据编程:

  1. il void work()
  2. {
  3. re int flag=1,tot=0,w=1,sum,ans=8;
  4. while(flag&&ans<16)
  5. {
  6. flag=0;
  7. fp(i,1,4)
  8. {
  9. tot=0;sum=0;w=1;
  10. fp(j,1,4) if(a[i][j]) ++tot,sum+=a[i][j];else w=j;
  11. if(tot==3) a[i][w]=h[i]-sum,flag=1,ans++;
  12. if(a[i][w]<=0&&tot==3) return;
  13. if(tot==4&&sum!=h[i]) return;
  14. }
  15. fp(i,1,4)
  16. {
  17. tot=0;sum=0;w=1;
  18. fp(j,1,4) if(a[j][i]) ++tot,sum+=a[j][i];else w=j;
  19. if(tot==3) a[w][i]=l[i]-sum,flag=1,ans++;
  20. if(a[w][i]<=0&&tot==3) return;
  21. if(tot==4&&sum!=l[i]) return;
  22. }
  23. if((a[1][1]>0)+(a[2][2]>0)+(a[3][3]>0)+(a[4][4]>0)==4&&a[1][1]+a[2][2]+a[3][3]+a[4][4]!=zs) return;
  24. if((a[1][1]>0)+(a[2][2]>0)+(a[3][3]>0)+(a[4][4]>0)==3)
  25. {
  26. sum=0;
  27. fp(i,1,4) sum+=a[i][i];
  28. fp(i,1,4) if(!a[i][i])
  29. {
  30. a[i][i]=zs-sum,flag=1,ans++;
  31. if(a[i][i]<=0&&tot==3) return;
  32. }
  33. }
  34. if((a[1][4]>0)+(a[2][3]>0)+(a[3][2]>0)+(a[4][1]>0)==4&&a[1][4]+a[2][3]+a[3][2]+a[4][1]!=zx) return;
  35. if((a[1][4]>0)+(a[2][3]>0)+(a[3][2]>0)+(a[4][1]>0)==3)
  36. {
  37. sum=0;
  38. fp(i,1,4) sum+=a[i][5-i];
  39. fp(i,1,4) if(!a[i][5-i])
  40. {
  41. a[i][5-i]=zx-sum,flag=1,ans++;
  42. if(a[i][5-i]<=0&&tot==3) return;
  43. }
  44. }
  45. if(flag==0&&ans<16)
  46. {
  47. re int tag=1;flag=1,ans++;
  48. fp(i,1,4)
  49. {
  50. fp(j,1,4) if(!a[i][j]) {a[i][j]=1,tag=0;break;}
  51. if(!tag) break;
  52. }
  53. }
  54. }
  55. if(ans==16)
  56. fp(i,1,4)
  57. {
  58. fp(j,1,4) printf("%d ",a[i][j]);
  59. puts("");
  60. }
  61. exit(0);
  62. }
  63. int main()
  64. {
  65. freopen("scrab.in","r",stdin);
  66. freopen("scrab.out","w",stdout);
  67. fp(i,1,4) h[i]=gi();fp(i,1,4) l[i]=gi();zs=gi(),zx=gi();
  68. fp(i,1,4) a[gi()+1][gi()+1]=gi();
  69. if(!a[2][2]&&tot<4) x[++tot]=2,y[tot]=2,a[2][2]=1;
  70. if(!a[2][3]&&tot<4) x[++tot]=2,y[tot]=3,a[2][3]=1;
  71. if(!a[3][2]&&tot<4) x[++tot]=3,y[tot]=2,a[3][2]=1;
  72. if(!a[3][3]&&tot<4) x[++tot]=3,y[tot]=3,a[3][3]=1;
  73. if(!a[1][1]&&tot<4) x[++tot]=1,y[tot]=1,a[1][1]=1;
  74. if(!a[1][4]&&tot<4) x[++tot]=1,y[tot]=4,a[1][4]=1;
  75. if(!a[4][1]&&tot<4) x[++tot]=4,y[tot]=1,a[4][1]=1;
  76. if(!a[4][4]&&tot<4) x[++tot]=4,y[tot]=4,a[4][4]=1;
  77. re int flag=1;
  78. fp(i,1,4) fp(j,1,4) if(a[i][j]) vis[i][j]=1;
  79. fp(i,1,80)
  80. fp(j,1,80)
  81. fp(k,1,80)
  82. fp(o,1,80)
  83. {
  84. a[x[1]][y[1]]=i;
  85. a[x[2]][y[2]]=j;
  86. a[x[3]][y[3]]=k;
  87. a[x[4]][y[4]]=o;
  88. work();
  89. fp(i,1,4) fp(j,1,4) if(!vis[i][j]) a[i][j]=0;
  90. }
  91. fclose(stdin);
  92. fclose(stdout);
  93. return 0;
  94. }

算法

从题意中我们可以看出,我们有个未知数,而有个方程。
于是就可以直接上消元了。
啥,有自由元?
枚举即可。
复杂度还是很玄学。。。

  1. #include<iostream>
  2. #include<cstdio>
  3. #include<cstdlib>
  4. #include<cstring>
  5. #include<cstdlib>
  6. #include<algorithm>
  7. #define ll long long
  8. #define re register
  9. #define il inline
  10. #define fp(i,a,b) for(re int i=a;i<=b;i++)
  11. #define fq(i,a,b) for(re int i=a;i>=b;i--)
  12. using namespace std;
  13. int a[100][100],id[10][10],n,ans[100];
  14. il int gi()
  15. {
  16. re int x=0,t=1;
  17. re char ch=getchar();
  18. while(ch!='-'&&(ch<'0'||ch>'9')) ch=getchar();
  19. if(ch=='-') t=-1,ch=getchar();
  20. while(ch>='0'&&ch<='9') x=x*10+ch-48,ch=getchar();
  21. return x*t;
  22. }
  23. il void Gauss()
  24. {
  25. fp(i,1,n)
  26. {
  27. re int now=i;
  28. fp(j,i+1,10)
  29. if(a[j][i]>a[now][i]) now=j;
  30. if(now^i) swap(a[i],a[now]);
  31. if(!a[i][i]) continue;
  32. fp(j,i+1,n)
  33. fq(k,n+1,i)
  34. a[j][k]-=a[i][k]*a[j][i]/a[i][i];
  35. }
  36. }
  37. il void Pre()
  38. {
  39. n=16;
  40. fp(i,1,4) fp(j,1,4) id[i][j]=(i-1)*4+j;
  41. fp(i,1,10) a[i][n+1]=gi();
  42. fp(i,1,4) fp(j,(i-1)*4+1,(i-1)*4+4) a[i][j]=1;
  43. fp(i,5,8) for(re int j=i-4;j<=16;j+=4) a[i][j]=1;
  44. a[9][1]=a[9][6]=a[9][11]=a[9][16]=1;
  45. a[10][4]=a[10][7]=a[10][10]=a[10][13]=1;
  46. fp(i,1,4)
  47. {
  48. re int x=gi()+1,y=gi()+1,z=gi();
  49. ans[id[x][y]]=z;
  50. fp(j,1,10) if(a[j][id[x][y]]) a[j][n+1]-=z,a[j][id[x][y]]=0;
  51. }
  52. fp(i,1,10)
  53. {
  54. fp(j,1,17) printf("%d ",a[i][j]);
  55. puts("");
  56. }
  57. }
  58. il void out()
  59. {
  60. fp(i,1,4)
  61. {
  62. fp(j,1,4) printf("%d ",ans[id[i][j]]);
  63. puts("");
  64. }
  65. exit(0);
  66. }
  67. il void dfs(re int x)
  68. {
  69. printf("!!!%d\n",x);
  70. if(x>16) out();
  71. if(ans[x]) dfs(x+1);
  72. else
  73. if(a[x][x])
  74. {
  75. ans[x]=a[x][n+1];
  76. fq(i,n,x+1) if(a[x][i]) ans[x]-=ans[i]/a[x][i];
  77. ans[x]/=a[x][x];
  78. dfs(x+1);
  79. }
  80. else
  81. {
  82. fp(i,1,80)
  83. {
  84. ans[x]=i;
  85. dfs(x+1);
  86. }
  87. }
  88. }
  89. int main()
  90. {
  91. Pre();
  92. Gauss();
  93. dfs(1);
  94. return 0;
  95. }
添加新批注
在作者公开此批注前,只有你和作者可见。
回复批注