第十四周 11.29-12.5

11.29-12.2

什么都没干。

12.3

偷的一个题目。

 

题意:

给一个N*N(N为偶数,N<=3000)的棋盘,上面放满黑白两面的棋子,我们用O表示白X表示黑,初始状态都是黑向上。

一次操作是选择一个棋子,与其同行或者同列的所有棋子(包括自己)翻面。

给一个最终局面,问:进行了几次操作?选择的是哪几个点?

 

分析:

首先选择的点在最终局面上一定是白子。

其次,对于最终局面的所有白子,无非两种情况。

1.操作中选择了这个子,并将与其同行同列的子翻转。

2.操作中选择了与这个子同行(列)的一个子翻转。

但是这两种白子具有区别。

由1.形成的白子其同行中的白子数等于其同列中的白子数。

简证:考虑初始局面,任意选一个位置翻,再选第二个位置翻的时候,必然与第一个子所在的行列都有且仅有一个交点。

   也就是使第一个子的行列都减少一个白子,同时我们注意到所有被选择翻的子其行列的白子数都是相等的,继续

   归纳即可。

由2.形成的白子其行列白子差为奇数,类似1.的方法来说明即可。

 

结论:在最终局面上寻找所有行列白子数相等的白子即为答案。

 

简陋datamaker

 1 #include <iostream>
 2 #include <cstdio>
 3 #include <cstring>
 4 #include <cstdlib>
 5 #include <ctime>
 6 #include <algorithm>
 7 using namespace std;
 8 const int maxn = 3030;
 9 char G[maxn][maxn];
10 int visx[maxn], visy[maxn];
11 
12 void init(int n)
13 {
14     memset(visx, 0, sizeof(visx));
15     memset(visy, 0, sizeof(visy));
16     for(int i = 1; i <= n; i++)
17         for(int j = 1; j <= n; j++)
18             G[i][j] = 'X';
19     return;
20 }
21 
22 void change(int n, int x, int y)
23 {
24     G[x][y] = G[x][y] == 'O' ? 'X' : 'O';
25     for(int i = 1; i <= n; i++)
26     {
27         if(i != y) G[x][i] = G[x][i] == 'O' ? 'X' : 'O';
28         if(i != x) G[i][y] = G[i][y] == 'O' ? 'X' : 'O';
29     }
30     return;
31 }
32 
33 void Print(int n)
34 {
35     printf("%d\n", n);
36     for(int i = 1; i <= n; i++)
37     {
38         for(int j = 1; j <= n; j++)
39             printf("%c", G[i][j]);
40         puts("");
41     }
42     return;
43 }
44 
45 int main(void)
46 {
47     srand(time(NULL));
48     freopen("data.txt","w",stdout);
49     FILE * f_out = fopen("ans.txt","w");
50     int T = 100, N = 3000;
51     printf("%d\n", T);
52     for(int i = 1; i <= T; i++)
53     {
54         int n = 1;
55         while( n % 2 == 1 ) n = rand() % (N - 1) + 1;
56         init(n);
57         int k = rand() % (n + 1), cnt = 0;
58         for(int j = 1; j <= 10000; j++)
59         {
60             if(cnt == k) break;
61             int x = rand() % (n - 1) + 1, y =  rand() % (n - 1) + 1;
62             if(visx[x] || visy[y]) continue;
63             cnt++;
64             visx[x] = visy[y] = 1;
65             change(n, x, y);
66         }
67         Print(n);
68         fprintf(f_out, "%d\n", min(k,cnt));
69     }
70     fclose(f_out);
71     return 0;
72 }
Aguin

 

简陋solver

 1 #include <iostream>
 2 #include <cstdio>
 3 #include <cstring>
 4 #include <vector>
 5 #include <algorithm>
 6 using namespace std;
 7 typedef pair<int,int> pii;
 8 const int maxn = 3030;
 9 char G[maxn][maxn];
10 int cntx[maxn], cnty[maxn];
11 
12 bool cmp(pii A, pii B)
13 {
14     if(A.first != B.first) return A.first < B.first;
15     return A.second < B.second;
16 }
17 
18 int main(void)
19 {
20     freopen("data.txt","r",stdin);
21     freopen("out.txt","w",stdout);
22     int T;
23     scanf("%d", &T);
24     while(T--)
25     {
26         int N;
27         scanf("%d", &N);
28         for(int i = 1; i <= N; i++)
29             scanf("%s", G[i] + 1);
30 
31         memset(cntx, 0, sizeof(cntx));
32         memset(cnty, 0, sizeof(cnty));
33 
34         for(int i = 1; i <= N; i++)
35             for(int j = 1; j <= N; j++)
36                 if(G[i][j] == 'O') cntx[i]++, cnty[j]++;
37 
38         vector<pii> ans;
39         for(int i = 1; i <= N; i++)
40         {
41             for(int j = 1; j <= N; j++)
42             {
43                 if(G[i][j] != 'O' || cntx[i] != cnty[j]) continue;
44                 ans.push_back(pii(i,j));
45             }
46         }
47 
48         int L = ans.size();
49         printf("%d\n", L);
50         if(L)
51         {
52             for(int i = 0; i < L; i++) printf("%d %d ", ans[i].first, ans[i].second);
53             puts("");
54         }
55     }
56     return 0;
57 }
Aguin

 

简陋judge

 1 #include <iostream>
 2 #include <cstdio>
 3 using namespace std;
 4 const int maxn = 3030;
 5 char G[maxn][maxn];
 6 
 7 void change(int n, int x, int y)
 8 {
 9     G[x][y] = G[x][y] == 'O' ? 'X' : 'O';
10     for(int i = 1; i <= n; i++)
11     {
12         if(i != y) G[x][i] = G[x][i] == 'O' ? 'X' : 'O';
13         if(i != x) G[i][y] = G[i][y] == 'O' ? 'X' : 'O';
14     }
15     return;
16 }
17 
18 bool judge(int n)
19 {
20     for(int i = 1; i <= n; i++)
21             for(int j = 1; j <= n; j++)
22                 if(G[i][j] != 'X') return false;
23     return true;
24 }
25 
26 void Print(int n)
27 {
28     printf("%d\n", n);
29     for(int i = 1; i <= n; i++)
30     {
31         for(int j = 1; j <= n; j++)
32             printf("%c",G[i][j]);
33         puts("");
34     }
35     return;
36 }
37 
38 int main(void)
39 {
40     FILE * f_in = fopen("data.txt","r");
41     FILE * f_ans = fopen("ans.txt","r");
42     FILE * f_user = fopen("out.txt","r");
43     int T;
44     fscanf(f_in, "%d", &T);
45     int ok = 1;
46     for(int kase = 1; kase <= T; kase++)
47     {
48         int N;
49         fscanf(f_in, "%d", &N);
50         for(int i = 1; i <= N; i++)
51             fscanf(f_in, "%s", G[i] + 1);
52 
53         int k, ans;
54         fscanf(f_user, "%d", &k);
55         fscanf(f_ans, "%d", &ans);
56 
57         for(int i = 1; i <= k; i++)
58         {
59             int x, y;
60             fscanf(f_user ,"%d%d",&x, &y);
61             change(N, x, y);
62         }
63 
64         if(k != ans) {ok = 0; printf("%d\n", kase);}
65         if(!judge(N)) {ok = 0; printf("%d\n", kase);}
66         //Print(N);
67     }
68     puts(ok ? "AC" : "WA");
69     fclose(f_in);
70     fclose(f_ans);
71     fclose(f_user);
72     return 0;
73 }
Aguin

 

如果N为奇数怎么做呢?

容易发现,在奇数棋盘中,对于上述的1.与2.也有一些性质。

由1.形成的白子,行列白子差为0,行列白子和为2n-2k+2(自己算两次,k为翻的次数)。

由2.形成的白子,行列白子差为|n-1-2k|(k为翻的次数),行列白子和为n+1(自己算两次)。

所以对于一般的情况,我们仍可以统计行列白子数来做。

但是当满足n=2k-1时,1.与2.形成的白子行列和差全部相同,就无法用这种方法来找了。

这个情况的做法至今没想出来。先弃了。

 

12.4

什么都没干。

 

12.5

打个BC。压线上紫。

看自己的曲线也不是一点长进都没有吧。

posted @ 2015-12-03 11:11  Aguin  阅读(175)  评论(0编辑  收藏  举报