Chinaunix首页 | 论坛 | 博客
  • 博客访问: 1559239
  • 博文数量: 327
  • 博客积分: 10000
  • 博客等级: 上将
  • 技术积分: 3556
  • 用 户 组: 普通用户
  • 注册时间: 2005-04-05 21:28
个人简介

东黑布衣,流浪幽燕。 真诚善良,值得信赖。

文章分类

全部博文(327)

我的朋友

分类: BSD

2017-06-03 17:04:58


  1. #include <stdio.h>
  2. #include <stdlib.h>
  3. #include <string.h>

  4. #define MAXN 15
  5. #define limit(x,y) ((x>=0) && (x<n) && (y>=0) && (y<n))
  6. int d[4][2]={{0,1},{1,0},{0,-1},{-1,0}};
  7. int n;
  8. int group[4][2*MAXN-1];
  9. int g[4][2*MAXN-1][3];//前两维与上面group一致,后面一维0:未确定 1:确定不放 2:确定放
  10. int board[MAXN][MAXN];
  11. int done;

  12. int color(int x, int y)
  13. {
  14.    int list[MAXN*MAXN][2];//que for bfs
  15.    int t,xx,yy,p,i;
  16.    list[0][0]=x;
  17.    list[0][1]=y;
  18.    board[x][y]=2;
  19.    t=1;p=0;
  20.    while(p<t){
  21.       for(i=0; i<4; i++){
  22.          xx=d[i][0]+list[p][0];
  23.          yy=d[i][1]+list[p][1];
  24.          if(limit(xx,yy) && (board[xx][yy]==0)){
  25.             board[xx][yy]=2;
  26.             list[t][0]=xx;
  27.             list[t][1]=yy;
  28.             t++;
  29.          }
  30.       }
  31.       p++;
  32.    }
  33.    return 0;
  34. }

  35. int enclosed_intersections()
  36. {
  37.    int i,j,k;
  38.    for(i=0; i<n; i++){
  39.       if(board[0][i]==0)
  40.          color(0,i);
  41.       if(board[n-1][i]==0)
  42.          color(n-1,i);
  43.    }

  44.    for(i=1; i<n-1; i++){
  45.       if(board[i][0]==0)
  46.          color(i,0);
  47.       if(board[i][n-1]==0)
  48.          color(i,n-1);
  49.    }

  50.    k=0;//统计封闭交叉点
  51.    for(i=0;i<n;i++){
  52.       for(j=0;j<n;j++){
  53.          if(board[i][j]==0)
  54.             k++;
  55.       }
  56.    }
  57.    return k;
  58. }

  59. int update(int board[MAXN][MAXN])
  60. {
  61.    int i,j,k,l,l1,l2;
  62.    int flag;//标记是否通过推断确定了某些新位置

  63.    /* 根据每行的约束条件进行推断 */
  64.    flag=0;
  65.    for(i=0;i<n;i++){
  66.       if(group[0][i]>g[0][i][2]+g[0][i][0])
  67.          return -1;//目标棋子数不能超过已放棋子+剩余位置数
  68.       //剩余位置都要放
  69.       if((g[0][i][0]>0) && (group[0][i]==g[0][i][2]+g[0][i][0])){
  70.          flag=1;
  71.          for(j=0;j<n;j++){
  72.             if(board[i][j]==-1)
  73.                board[i][j]=1;
  74.          }
  75.       }
  76.       //剩余位置都不能放
  77.       if((g[0][i][0]>0) && (group[0][i]==g[0][i][2])){
  78.          flag=1;
  79.          for(j=0;j<n;j++){
  80.             if(board[i][j]==-1)
  81.                board[i][j]=0;
  82.          }
  83.       }
  84.    }
  85.    if(flag)
  86.       return 1;
  87.    /* 根据每列的约束条件进行判断 */
  88.    for(j=0;j<n;j++){
  89.       if(group[1][j]>g[1][j][2]+g[1][j][0])
  90.          return -1;
  91.       if((g[1][j][0]>0) && (group[1][j]==g[1][j][2]+g[1][j][0])){
  92.          flag=1;
  93.          for(i=0;i<n;i++){
  94.             if(board[i][j]==-1)
  95.                board[i][j]=1;
  96.          }
  97.       }
  98.       if((g[1][j][0]>0) && (group[1][j]==g[1][j][2])){
  99.          flag=1;
  100.          for(i=0;i<n;i++){
  101.             if(board[i][j]==-1)
  102.                board[i][j]=0;
  103.          }
  104.       }
  105.    }
  106.    if(flag)
  107.       return 1;

  108.    /* 根据每条对角线的约束条件进行判断 */
  109.    for(k=0;k<2*n-1;k++){
  110.       if(group[2][k]>g[2][k][2]+g[2][k][0])
  111.          return -1;
  112.       if((g[2][k][0]>0) && (group[2][k]==g[2][k][2]+g[2][k][0])){
  113.          flag=1;
  114.          if(k<=n-1){
  115.             l1=0;
  116.             l2=k;
  117.          }else{
  118.             l1=k-n+1;
  119.             l2=n-1;
  120.          }
  121.          for(l=l1;l<=l2;l++){
  122.             if(board[l][k-l]==-1)
  123.                board[l][k-l]=1;
  124.          }
  125.       }
  126.       if((g[2][k][0]>0) && (group[2][k]==g[2][k][2])){
  127.          flag=1;
  128.          if(k<=n-1){
  129.             l1=0;
  130.             l2=k;
  131.          }else{
  132.             l1=k-n+1;
  133.             l2=n-1;
  134.          }
  135.          for(l=l1;l<=l2;l++){
  136.             if(board[l][k-l]==-1)
  137.                board[l][k-l]=0;
  138.          }
  139.       }
  140.    }
  141.    if(flag)
  142.       return 1;
  143.          
  144.    /* 根据每条反对角线的约束条件进行判断 */
  145.    for(k=0;k<2*n-1;k++){
  146.       if((group[3][k]>g[3][k][2]+g[3][k][0]))
  147.          return -1;
  148.       if((g[3][k][0]>0) && (group[3][k]==g[3][k][2]+g[3][k][0])){
  149.          flag=1;
  150.          if(k<=n-1){
  151.             l1=n-1-k;
  152.             l2=n-1;
  153.          }else{
  154.             l1=0;
  155.             l2=2*n-2-k;
  156.          }
  157.          for(l=l1;l<l2;l++){
  158.             if(board[l][k+l-n+1]==-1)
  159.                board[l][k+l-n+1]=1;
  160.          }
  161.       }
  162.       if((g[3][k][0]>0) && (group[3][k]==g[3][k][2])){
  163.          flag=1;
  164.          if(k<=n-1){
  165.             l1=n-1-k;
  166.             l2=n-1;
  167.          }else{
  168.             l1=0;
  169.             l2=2*n-2-k;
  170.          }
  171.          for(l=l1;l<l2;l++){
  172.             if(board[l][k+l-n+1]==-1)
  173.                board[l][k+l-n+1]=0;
  174.          }
  175.       }
  176.    }
  177.    if(flag)
  178.       return 1;
  179.    return 0;
  180. }

  181. int deduce(int board[MAXN][MAXN])
  182. {
  183.    int i,j,k,flag;
  184.    flag=1;
  185.    while(flag){
  186.       memset(g,0,sizeof(g));
  187.       for(i=0;i<n;i++){
  188.          for(j=0;j<n;j++){
  189.             k=board[i][j];
  190.             g[0][i][k+1]++;
  191.             g[1][j][k+1]++;
  192.             g[2][i+j][k+1]++;
  193.             g[3][j-i+n-1][k+1]++;
  194.          }
  195.       }

  196.       flag=update(board);
  197.       if(flag==-1)
  198.          return -1;
  199.    }
  200.    return 0;
  201. }

  202. int init()//读入数据和完成初始化
  203. {
  204.    int i;
  205.    memset(group,0,sizeof(group));
  206.    memset(board,0xFF,sizeof(board));

  207.    for(i=0;i<n;i++){
  208.       scanf("%d", &group[0][i]);
  209.    }
  210.    for(i=0;i<n;i++)
  211.       scanf("%d", &group[1][i]);
  212.    for(i=0;i<n*2-1;i++)
  213.       scanf("%d", &group[2][i]);
  214.    for(i=0;i<n*2-1;i++)
  215.       scanf("%d", &group[3][i]);

  216.    board[0][0]=group[2][0];
  217.    board[n-1][n-1]=group[2][2*n-2];
  218.    board[n-1][0]=group[3][0];
  219.    board[0][n-1]=group[3][2*n-2];

  220.    deduce(board);
  221.    return 0;
  222. }

  223. int solutionfound(int* x,int* y)
  224. {
  225.    int i,j;
  226.    for(i=0; i<n;i++){
  227.       for(j=0; j<n;j++){
  228.          if(board[i][j]==-1){
  229.             *x=i;
  230.             *y=j;
  231.             return 0;
  232.          }
  233.       }
  234.    }
  235.    return 1;
  236. }

  237. int right()
  238. {
  239.    int i,j,k;
  240.    memset(g,0,sizeof(g));
  241.    for(i=0;i<n;i++){
  242.       for(j=0;j<n;j++){
  243.          k=board[i][j];
  244.          g[0][i][k+1]++;
  245.          g[1][j][k+1]++;
  246.          g[2][i+j][k+1]++;
  247.          g[3][j-i+n-1][k+1]++;
  248.       }
  249.    }

  250.    for(i=0;i<n;i++){
  251.       if(g[0][i][2] != group[0][i])
  252.          return 0;
  253.       if(g[1][i][2] != group[1][i])
  254.          return 0;
  255.    }

  256.    for(i=0;i<2*n-1;i++){
  257.       if(g[2][i][2] != group[2][i])
  258.          return 0;
  259.       if(g[3][i][2] != group[3][i])
  260.          return 0;
  261.    }
  262.    return 1;
  263. }

  264. //依次对棋盘位置搜索,尝试放与不放棋子来找出棋盘布局
  265. int attempt()
  266. {
  267.    int oldboard[MAXN][MAXN];
  268.    int x,y,k;
  269.    if(solutionfound(&x,&y)){
  270.       if(right()){
  271.          done=1;
  272.       }
  273.       return 0;
  274.    }

  275.    memcpy(oldboard,board,sizeof(board));//save original chessboard
  276.    board[x][y]=1;//try to putting chess
  277.    k=deduce(board);
  278.    if(k!=-1){
  279.       attempt();
  280.       if(done)
  281.          return 0;
  282.    }

  283.    memcpy(board,oldboard,sizeof(board));//restore old chessboard
  284.    board[x][y]=0;//try to no putting chess
  285.    k=deduce(board);
  286.    if(k!=-1){
  287.       attempt();
  288.       if(done)
  289.          return 0;
  290.    }
  291.    memcpy(board,oldboard,sizeof(board));
  292.    return 0;
  293. }

  294. int run()
  295. {
  296.    done=0;
  297.    attempt();
  298.    return 0;
  299. }

  300. int main()
  301. {
  302.    int test_case,T;
  303.    freopen("0503in.txt","r",stdin);
  304.    //freopen("0503out.txt","w",stdout);
  305.    //setbuf(stdout,NULL);
  306.    scanf("%d", &T);
  307.    for(test_case=1;test_case<=T;test_case++)
  308.    {
  309.       scanf("%d", &n);
  310.       init();
  311.       run();
  312.       printf("%d\n", enclosed_intersections());
  313.    }
  314.    return 0;
  315. }

Input:
10
1
1
1
1
1
15
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
15
15 15 15 15 15 15 15 15 15 15 15 15 15 15 15
15 15 15 15 15 15 15 15 15 15 15 15 15 15 15
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1
5
1 3 2 3 1
0 2 2 2 4
0 0 1 3 0 2 2 1 1
0 0 0 2 3 2 1 2 0
15
15 2 13 13 13 13 13 13 13 13 13 13 13 2 15
15 2 13 13 13 13 13 13 13 13 13 13 13 2 15
1 2 2 2 3 4 5 6 7 8 9 10 11 12 13 12 11 10 9 8 7 6 5 4 3 2 2 2 1
1 2 2 2 3 4 5 6 7 8 9 10 11 12 13 12 11 10 9 8 7 6 5 4 3 2 2 2 1
10
10 2 2 2 2 2 2 2 2 9
10 2 2 2 2 2 2 2 2 9
1 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 0
1 2 2 2 2 2 2 2 2 1 2 2 2 2 2 2 2 2 1
10
0 8 2 2 2 2 2 2 8 0
0 8 2 2 2 2 2 2 8 0
0 0 1 2 2 2 2 2 2 2 2 2 2 2 2 2 1 0 0
0 0 1 2 2 2 2 2 2 2 2 2 2 2 2 2 1 0 0
10
1 1 1 1 1 1 1 1 1 1
0 0 0 0 10 0 0 0 0 0
0 0 0 0 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0
0 0 0 0 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0
15
2 2 2 2 2 2 2 1 2 2 2 2 2 2 2
2 2 2 2 2 2 2 1 2 2 2 2 2 2 2
1 0 1 0 1 0 1 0 1 0 1 0 1 0 15 0 1 0 1 0 1 0 1 0 1 0 1 0 1
1 0 1 0 1 0 1 0 1 0 1 0 1 0 15 0 1 0 1 0 1 0 1 0 1 0 1 0 1
15
12 6 6 5 5 5 5 5 8 4 4 4 4 4 11
12 6 6 5 4 4 4 9 4 3 4 4 4 4 15
0 2 2 4 0 6 2 2 2 10 0 12 2 2 2 2 7 6 3 3 3 3 2 2 2 2 2 2 1
1 2 2 1 1 2 2 4 4 5 3 6 3 6 1 6 3 7 2 6 2 5 2 4 1 2 2 2 1

Out:
iLyn:acm02 Cute$ time ./0503
0
0
0
3
48
64
36
0
0
122
real    0m0.008s
user    0m0.001s
sys    0m0.003s



阅读(1370) | 评论(0) | 转发(0) |
0

上一篇:[20170524 ADV] Hourglasses

下一篇:lc0048

给主人留下些什么吧!~~