博客

  • [未完成]USACO 1.4.1 Prime Cryptarithm

      这是这一次做USACO目前唯一一个没做完的题目!第六种情况实在是不知道怎么写,我觉得最好还是不写最好,所以就没去写了。我也尝试了一下自己试着写写,结果写了最后一种情况竟然还不如不写的分数高!但是自己实在是不知道为什么,以前的代码这三行(最后一种情况)也是抄的,不是理解的,所以现在也就忘了……
      我的思路就是暴搜,用srch0将所用的矩形换位置,srch1将所有的矩阵的长宽交换,然后用count进行判断,代码十分易读(以前别人写的,不过因为确实有特色,所以已经变成了自己的东西了。)
      总结一下错误:

      1、把return忘记了,会进入死循环。
      2、递归调用时应该是srch(0)而不是n + 1。
      3、在记录答案时竟然没有判断。
      4、在一种情况的时候把y写成了x。
      注意:本程序还没AC,但是要他AC只需要最后的两个if,因为我不理解缘由,所以没写第六种情况(代码中注释好了!)
    /
    LANG: C
    ID: yylogoo2
    PROG: packrec
    /
    #include <math.h>
    #include <stdio.h>
    #include <string.h>
    struct box{
            int x, y;
    }box[4];
    int place[4];
    int ans = 2501;
    int take[2501];

    void check(int x, int y)
    {
            if(x y < ans){
                    ans = x
    y;
                    memset(take, 0, sizeof(take));
            }
            /
            Mistack 3:
              没经过任何判断就直接把x, y作为答案了,那么就错了!! 
            即刚刚忘记敲入if了。 
            
    /
            if(x y == ans){
                    take[x] = 1;
                    take[y] = 1;
            }
    }

    int max(int a, int b)
    {
            return a > b ? a : b;
    }

    void count(int x1, int y1, int x2, int y2,
                    int x3, int y3, int x4, int y4)
    {
            int x, y;

            x = x1 + x2 + x3 + x4;
            y = max(max(y1, y2), max(y3, y4));
            check(x, y);

            x = max(x1, x2 + x3 + x4);
            y = y1 + max(y2, max(y3, y4));
            check(x, y);

            x = max(x1, x2 + x3) + x4;
            y = max(y4, y1 + max(y2, y3));
            check(x, y);

            x = x1 + max(x2, x3) + x4;
            /

            Mistack 4:
              下面把y写成了x
            /
            y = max(y2 + y3, max(y1, y4));
            check(x, y);

            / 最后一种情况 /
    }

    void output(void)
    {
            int i, limit;
            printf("%d\n", ans);
            limit = sqrt(ans);
            for(i = 1; i <= limit; i++){
                    if(take[i]){
                            printf("%d %d\n", i, ans / i);
                    }
            }
    }

    void change(struct box a)
    {
            a->x ^= a->y;
            a->y ^= a->x;
            a->x ^= a->y;
    }

    void srch1(int now)
    {
            if(now == 4){
                    count(  box[place[0]].x, box[place[0]].y,
                            box[place[1]].x, box[place[1]].y,
                            box[place[2]].x, box[place[2]].y,
                            box[place[3]].x, box[place[3]].y);
                    return;
            }
            srch1(now + 1);
            change(&box[place[now]]);
            srch1(now + 1);
            change(&box[place[now]]);
    }

    int used[4];

    void srch0(int now)
    {
            int i;
            if(now == 4){
                    /
                    Mistack 2:
                      是调用srch1(0)而不是srch(now + 1)
                    
    /
                    srch1(0);
                    /
                    Mistack 1:
                      把函数返回掉了…那样会死循环的..
                    
    /
                    return;
            }
            for(i = 0; i < 4; i++){
                    if(!used[i]){
                            used[i] = 1;
                            place[now] = i;
                            srch0(now + 1);
                            used[i] = 0;
                    }
            }
    }

    int main(void)
    {
            int i;
            freopen("packrec.in", "r", stdin);
            freopen("packrec.out", "w", stdout);
            for(i = 0; i < 4; i++){
                    scanf("%d%d", &box[i].x, &box[i].y);
            }
            srch0(0);
            output();
            return 0;
    }

  • USACO 1.3.4 Prime Cryptarithm

      我没找到什么很巧的方法,纯暴力搜索:
      枚举100~999,10~99然后再分别进行判断,是各个数值否是在范围内,然后是否是输入输入的集合,如果都是ans递增,代码就是这样,犯了两个错误!
      1、在比较是否属于全集时,我是判断如果都不属于才算不属于,即用的“与”进行连接,应用“或”连接,在有一个不属于全集时就算不属于了。
      2、在判断是否是千位数时我用的是i >= 999,应该用i>999。
      不过都是打代码就发现的问题,所以一次性AC!

    /
    ID: yylogoo2
    PROG: crypt1
    LANG: C
    /
    #include <stdio.h>
    int num[9];
    int used[10];
    int n;
    int ans;
    int tmp[2];

    void count(int a, int b)
    {
            int i, j;
            /
            Mistack 1:
              下面用错逻辑符号了,改用||而用了&&
            
    /
            if(!check(a) || !check(b)){
                    return;
            }
            i = a (b % 10);
            j = a
    (b / 10);
            /
            Mistack 2:
              不允许为千位数,但是允许为999。 
            
    /
            if((i > 999) || (j > 999)){
                    return ;
            }
            if(!check(i) || !check(j)){
                    return ;
            }
            i = a b;
            if((i >= 1000) && (i <= 9999) && check(i)){
                    ans++;
            }
    }

    int check(int k)
    {
            while(k != 0){
                    if(!used[k % 10]){
                            return 0;
                    }
                    k /= 10;
            }
            return 1;
    }

    int main(void)
    {
            int i, j;
            freopen("crypt1.in", "r", stdin);
            freopen("crypt1.out", "w", stdout);
            scanf("%d", &n);
            for(i = 0; i < n; i++){
                    scanf("%d", &num[i]);
                    used[num[i]] = 1;
            }
            for(i = 100; i <= 999; i++){
                    for(j = 10; j <= 99; j++){
                            if(i
    j > 9999){
                                    break;
                            }
                            count(i, j);
                    }
            }
            printf("%d\n", ans);
            return 0;
    }

  • 算法: 求最长的回文

      最近USACO写到了(第三次)1.3.3,这一题(http://zqynux.blog.163.com/blog/static/16749959720109291375436/)我用的是我自己原创的一个算法(可能也有别人想到了,但是对于我来说,确实是我自己独立思考出来的),在此发表一下。
      程序:输入:一行字符串,输出:最长的回文字符的长度以及把它们给输出来。
      如:

        输入:1596156432111234
        输出:6
           432111234
    回文的性质
      首先先把题目撇开,单说回文数的性质,如abcba是一个长度为5的回文数,那它有什么性质呢?
      回文数顾名思义,就是从左念和从右念是相同的,也可以说从左遍历和从右遍历是相同的,这些都是废话。因为它是回文数所以可以同时从左和右开始遍历,各个字符都是相同的。
      其实上面那些性质也没什么用,算是铺垫吧,接下来的才是重点,那怎么样去构成一个回文数呢?就用abcba做例子吧,这个回文数的构成是由单个字符c两边同时放置b,构成的bcb再两边同时放置一个a构成的。
    回文的判定
      那么假设要你判断abcba是不是有两种方法,但是我要说的不是两边同时开始遍历并且判断的方法,再用abcbad做例子吧,用程序判断它是不是一个回文数,我先把过程写出来,然后再把方式写出来。
      下面把回文数和回文混用。
      首先下标i=0…5,s[i]代表第i个字符。i从1开始递归,因为第一个字符不存在回文数,i=1时,当前回文长度为1,就是单个字符a。当前回文数长度是我自己定义的名词,就是说以i结尾的回文数的长度。然后i = 2时,当前回文数是单个字符c,长度为1;i=3时,这里需要注意一下了,从这里开始就有一些变化了,当前回文数的长度为3,为bcb,i=4时,当前回文数的长度为5,为abcba,接着i=5,当前回文长度为1,是单个字符d,这样它就不是一个回文数。
    当前回文数长度
      那么求当前回文数的长度(不是标准的语言):
      i = 1
      while(i < n){
        if(s[start[i – 1] – 1] == s[i]){
          start[i] = start[i – 1] – 1;
          len[i] = len[i – 1] + 2;
        }else if(s[i – 1] == s[i]){
          start[i] = i – 1;
          len[i] = 2;
        }else{
          start[i] = i;
          len[i] = 1;
        }
      }
      上面的start[i]代表当前回文数的开始下表,len[i]是当前回文数的长度,就比如说123321吧,当i = 3时(123321),start[i] = 2(123321) len[i] = 2;当i = 5时(123321),start[i] = 0(123321),len[i] = 6,也就是说当前回文数的取决于三种情况:
      第一种:start[i – 1]的前面一个字符等于i时,当前回文就是(start[i – 1] – 1) ~ i,长度就是len[i – 1] + 2。
      第二种:s[i – 1]等于s[i],就是说两个相邻的字符相等的话,那么start[i] = i – 1;len[i] = 2。
      第三种:什么都不是,就是单个字符回文,start[i] = i, len[i] = 1。
      其实仔细想想可以把len[]这个数组去掉,因为len[i] = i – start[i] + 1;
      但是,因为这篇文章时根据USACO那题写的,那个题目的s中包含空格和标点符号,但是又把它们记入len[]中,所以这个代码只是一个模式,遇到不同的题目要有不同的待遇,但是这种思想我觉得很重要/神奇,类似于DP但又不是。
    解题
      那么上面的题目就好解了(只给出大致代码):
      i = 1, ans = 0
      while(i < n){
        if(s[start[i – 1] – 1] == s[i]){
          start[i] = start[i – 1] – 1;
          len[i] = len[i – 1] + 2;
        }else if(s[i – 1] == s[i]){
          start[i] = i – 1;
          len[i] = 2;
        }else{
          start[i] = i;
          len[i] = 1;
        }
        if(ans < len[i]){
          ans = len[i];
          k = i;
        }
      }
      printf("%d\n", ans);
      for(i = start[k]; i <= k; i++){
        printf("%c", s[i]);
      }
      自己发明的算法,文本上没有什么可以参考的蓝本,写得不好请见谅。

  • USACO 1.3.3 Calf Flac

      这一题是USACO所有题目中我最自豪的一个题目,首先因为大部分人的代码都是在小数后一位上,而我这个算法是O(n)的,所以非常的快。又因为这是我自己想出来的,而且思维角度比较独特,所以我甚为自豪!
      但是我这个思路很难表达清晰。
      想把它单独提出来作为一篇文章(http://zqynux.blog.163.com/blog/static/1674995972010929683892/)写,包裹题解也在左边的链接里面,写好了把链接贴上来。
      这里我犯的几个错误分别如下:

      1、在比较不同字母时没注意大小写的区分。
      2、在查找对应的字母时应该是查找start[i – 1] – 1之前的一个字母而不是start[i] – 1。
      3、在循环该结束时忘记continue;了。
      感觉写得比较好,代码如下:
    /
    LANG: C
    ID: yylogoo2
    PROG: calfflac
    /
    #include <ctype.h>
    #include <stdio.h>
    #include <string.h>
    #define EQ(a, b) (toupper(a) == toupper(b))
    char str[20001];
    / 记录以i结尾的回文数的另外一头的坐标:start[i] /
    int start[20001];
    / 记录纯净长度, 把空格和标点符号去掉的长度 /
    int num[20001];

    / 寻找一个字母, way 为1时向后寻找, way为-1时向前寻找 /
    int find(int s, int way)
    {
            int t = s;
            while(t >= 0 && !isalpha(str[t])){
                    t += way;
            }
            return t;
    }

    int main(void)
    {
            int i, t, j;
            int len = 0;
            int max = 1;
            int end = 0;
            freopen("calfflac.in", "r", stdin);
            freopen("calfflac.out", "w", stdout);
            while(fgets(&str[len], 20000 – len, stdin) != NULL){
                    len += strlen(&str[len]);
            }
            for(i = 1; i < len; i++){
                    if(!isalpha(str[i])){
                            num[i] = num[i – 1];
                            start[i] = start[i – 1];
                            /
                            Mistack 3:
                              忘记添加continue了,进入这个的时候num[i]就会改变,
                            下一次DP时会有错误。
                            
    /
                            continue;
                    }
                    /
                    Mistack 2:
                      下面应该是使用start[i – 1]的前一个字符进行比较 
                    
    /
                    t = find(start[i – 1] – 1, –1);
                    /
                    Mistack 1:
                      在比较字母是否相等时,忽略了大小写。 
                    
    /
                    if(t >= 0 && EQ(str[t], str[i])){
                            num[i] = num[i – 1] + 2;
                            start[i] = t;
                    }else{
    /                      t = find(i – 1, -1);
                            j = find(i + 1, 1);
                            if(str[t] == str[j]){
                                    num[i] = 3;
                                    start[i] = t;
                            }else if(str[t] == str[i]){
                                    num[i] = 2;
                                    start[i] = t;
                            }
    /
                            t = find(i – 1, –1);
                            if(t > 0 && EQ(str[i], str[t])){
                                    num[i] = 2;
                                    start[i] = t;
                            }else{
                                    num[i] = 1;
                                    start[i] = i;
                            }
                    }
                    if(num[i] > max){
                              max = num[i];
                              end = i;
                    }
            }
            printf("%d\n", max);
            for(i = start[end]; i <= end; i++){
                    printf("%c", str[i]);
            }
            printf("\n");
            return 0;
    }

  • USACO 1.3.2 Barn Repair

      这一题想了好久才想起来以前是怎么做的,直接使用的贪心,首先假设只有一块木板,自然而然是从最小的到最大的全部盖上,此时假设值为ans,那么如果是两块木板,那两块木板之间隔的距离必定是整个牛棚中距离最远的两个牛之间的距离,也就是说答案等于:只有一块木板的长度减去一个最长间隔:ans-max(dis),那三块木板的话很自然就是只有一块木板的长度减去最长的前两个间隔的值,以此类推,代码就很简单了。
      但是又由于需要快排的实现,我嫌它麻烦了,就直接使用数组进行排序(这个排序方法准确叫什么名字我也忘了,不记得是基数还是桶还是哈希排序了。),因为数据量并不是特别的大,所以使用这种排序方法也会比快排要好很多(至少自我感觉是这样,我的应该是O(n)而快排最快O(n logn))!
      这也是少量提交了两次的题目:

      1、在程序中如果有n块木板的话,相当于只有一块木板,其中有n-1个洞;也就是说一块肉要3块只要切2刀即可。j = 1; j < m
      2、比如已有a, b 两点(b > a),代表两个位置,那么b – a – 1代表的是把两点除去,剩下的个数,而b – a + 1代表包括亮点总共的长度,在求只要一块木板长度时应该是b-a+1,我写的是b-a-1。
      3、程序的设计有误,求下一点应该是从+1开始而不是从当前点开始,这一个我不好形象点地说出来,只能说j要从1开始,之后的内容要修改成dis[j – 1]++。
      下面这个是第二次提交之后发现的问题。
      4、下面的代码忽略了一个重要的问题:
    for(i = s – 1; i >= 0 && j < m; i–){
    if(dis[i] > 0){
    ans -= i;
    j++;
    dis[i]–;
    }
    }
      当dis[i] > 1时只计算一次,剩下的次数就不算了。。
      修改之后(在dis[i]–;后面插入i++;一行)就能够应付了。
      还有一个要注意的,就是在循环体退出之后还要一个dis[j – 1]–;因为前面会把最后一个牛和结尾的墙壁之间的距离当作需要考虑的距离来算,要将它除去。
    /
    LANG: C
    ID: yylogoo2
    PROG: barn1
    /
    #include <stdio.h>
    int cow[200];
    int dis[200];

    int main(void)
    {
            int t;
            int i, j;
            int m, s, c;
            int fi = 200, la = –1;
            unsigned ans;
            freopen("barn1.in", "r", stdin);
            freopen("barn1.out", "w", stdout);
            scanf("%d%d%d", &m, &s, &c);
            for(i = 0; i < c; i++){
                    scanf("%d", &t);
                    cow[t – 1]++;
                    if(t – 1 < fi){
                            fi = t – 1;
                    }
                    if(t – 1 > la){
                            la = t – 1;
                    }
            }
            i = fi;
            while(i < s){
                    /
                    Mistack 3:
                      下面应该从1开始,而不是0,不然会进入死循环,
                    但是下面改成一之后dis[j]++就要改成dis[j – 1]++。
                    
    /
                    for(j = 1; (cow[i + j] == 0) && (i + j < s); j++){
                    }
                    dis[j – 1]++;
                    /
                    Pay attention:
                      下面-1的原因是再进行计算一次
                    
    /
                    i += j;
            }
            /
              下面的代码是把最后一个位置和结尾之间的空隙删除了
            其实它可以放在上面的循环体内, 但是这样的话每次循环都
            要判断一次, 很慢!!
            
    /
            dis[j – 1]–;
            /
            Mistack 2:
              下面应该是要+1而不是-1
            +1代表包括两点中间的距离,
            -1代表出去两点中间的距离。
            
    /
            ans = la – fi + 1;
            /
            Mistack 1:
              下面应该是从1开始而不是0, 因为把一块肉切成3分的话,只要2刀 
            
    /
            j = 1;
            /
            Mistack 4:
              下面的代码忽略了一个重要的问题:
            for(i = s – 1; i >= 0 && j < m; i–){
                    if(dis[i] > 0){
                            ans -= i;
                            j++;
                            dis[i]–;
                    }
            }
              当dis[i] > 1时只计算一次,剩下的次数就不算了。。
              修改之后(在dis[i]–;后面插入i++;一行)就能够应付了。 
            
    /
            for(i = s – 1; i >= 0 && j < m; i–){
                    if(dis[i] > 0){
                            ans -= i;
                            j++;
                            dis[i]–;
                            i++;
                    }
            }
            printf("%u\n", ans);
            return 0;
    }

  • USACO 1.3.1 Mixing Milk

      这题是个纯贪心题,本来是打算使用快排的,想到考试时可能不允许使用快排,自己写又太麻烦了,所以我就懒得用快排了,题目的数据量也不是很大,直接使用数组进行排序就是!
      当然没有什么明显的问题,一次AC,代码如下:

    /
    LANG: C
    ID: yylogoo2
    PROG: milk
    /
    #include <stdio.h>
    unsigned milk[1001];

    int main(void)
    {
            int n, m;
            int i, got = 0, ans = 0;
            unsigned a, b;
            freopen("milk.in", "r", stdin);
            freopen("milk.out", "w", stdout);
            scanf("%d%d\n", &n, &m);
            for(i = 0; i < m; i++){
                    scanf("%u%u\n", &a, &b);
                    milk[a] += b;
            }
            for(i = 0; got != n; i++){
                    if(milk[i] != 0){
                            if(milk[i] + got > n){
                                    ans += (n – got) i;
                                    got = n;
                            }else{
                                    ans += milk[i]
    i;
                                    got += milk[i];
                            }
                    }
            }
            printf("%u\n", ans);
            return 0;
    }

  • USACO 1.2.5 Dual Palindromes

      本来应该是很简单的一个题目,因为昨天才写前面一题(USACO 1.2.4 Palindromic Squares),就是使用那里写的一些子函数即可AC,但是因为现在是以学习为目的,所以自然是重写一次,但是重写同样的两个函数,却出现了不应该有的错误,具体错误如下:

      1、在循环之后忘记更改循环变量了,就是说比如:for(i = 0; i <= 10; / 相当于这里没写 / ),自然循环就无法结束了!
      2、在数组里面直接使用长度作为下表,又比如:char str[10] = "12345",而我想通过str[strlen(str)]来指向最后一个字符,明显是错误!应该是str[strlen(str) – 1]才能使用最后一个字符!
      和昨天的代码比较了一下,昨天的代码层次性更强,直接将字符串的长度作为参数传给了判断是否为回文数的函数,而今天是在判断回文数的函数内部进行的!
      不过因为没有别的问题,所以还是一次性AC了:
    /
    LANG: C
    ID: yylogoo2
    PROG: dualpal
    /
    #include <stdio.h>
    #define STR "0123456789"
    #define MAX 50
    char str[MAX];

    int change(int num, int base)
    {
            int i = MAX;
            while(num != 0){
                    str[–i] = STR[num % base];
                    num /= base;
            }
            return i;
    }

    int ispal(int start)
    {
            char num = &str[start];
            /

            Mistack 2:
              下面j的赋值错误了。第一次是写成了j = MAX – i, 后来修改成了j = MAX – i – 1  还是错了
            最后一次才改对.. 
            /
            int i = 0, j = MAX – start – 1;
            while(i < j){
                    if(num[i] != num[j]){
                            return 0;
                    }
                    /

                    Mistack 1:
                       忘记下面的递增和递减!
                    */
                    i++, j–;
            }
            return 1;
    }

    int main(void)
    {
            int i, j, k, l;
            int m, n;
            freopen("dualpal.in", "r", stdin);
            freopen("dualpal.out", "w", stdout);
            scanf("%d%d", &m, &n);
            for(i = n + 1, k = 0; k < m; i++){
                    l = 0;
                    for(j = 2; j <= 10 && l != 2; j++){
                            if(ispal(change(i, j))){
                                    l++;
                            }
                    }
                    if(l == 2){
                            printf("%d\n", i);
                            k++;
                    }
            }
            return 0;
    }

  • USACO 1.2.4 Palindromic Squares

      这题硬搜就是,不过在提交前找到两个mistack:

      1、没审清楚题目,题目只要求平方是回文数,而没有要求那个数自身也是个回文数,我以为那个数自身也是回文数。
      2、在转换进制的时候,犯了一个超级低级的错误,把进制顺着使用了,也就是说比如13的二进制是:1101,而我的程序做出来就是1011,弄翻了!当然,很快就改好了,提交,一次性AC!
    /
    LANG:
    C

    ID: yylogoo1
    PROG:
    palsquare

    /
    #include <stdio.h>
    #define MAP
    "0123456789ABCDEFGHIJ"
    #define MAX 18
    int n;
    char str[MAX];

    int isreback(char str, int len)
    {
            int i, j;
            i = 0, j = len – 1;
            while(i < j){
                    if(str[i++] !=
    str[j–]){
                            return 0;
                    }
            }
            return 1;
    }

    int change(int num)
    {
            /

            mistack
    2:

              这里写错了,str应该是逆向的方式写的!
            /
            int i = MAX;
            while(num != 0){
                    str[–i] = MAP[num %
    n];
                    num /= n;
            }
            return i;
    }

    int ispal(int num)
    {
            int i, len;
            i =
    change(num);
            len = MAX – i;
            return isreback(&str[i], len);
    }

    void output(int num)
    {
            printf("%s",
    &str[change(num)]);
    }

    int main(void)
    {
            int i;
            freopen("palsquare.in", "r", stdin);
            freopen("palsquare.out", "w", stdout);
            scanf("%d", &n);
            for(i = 1; i <= 300; i++){
                    /

                    mistack
    1:

                      题目没审清楚,  只要求平方是回文数,
                    而没要求自己也是回文数数
                    /
                    if(ispal(i

    i)){
                            output(i);
                            printf(" ");
                            output(i *
    i);
                            printf("\n");
                    }
            }
            return 0;
    }

  • USACO 1.2.3 Name That Number

      这题我用的方法就是将dict.txt中的每一个字符串读出来,并判断是否满足输入的那个数字,如果满足输出就是。
      我还有另外一个算法,就是首先根据输入的数字来确定范围,然后逐步缩小,最后确定到个数,但是很快就发现这是(我)无法实现的高难度算法。
      再一个,我上面的那个算法要注意的是数的长度,最长是12位的数字!int存不进,必须要用long long!
      代码如下:

    /
    LANG: C
    ID: yylogoo1
    PROG: namenum
    /
    #include <stdio.h>
    #include <assert.h>
    FILE fp;
    char str[13];
    char map[26] = {2, 2, 2, 3, 3, 3, 4, 4, 4, 5, 5, 5, 6, 6, 6,
            7, 0, 7, 7, 8, 8, 8, 9, 9, 9, 0};

    long long change(char str)
    {
            long long t = 0;
            while(str != ‘\0’){
                    t
    = 10;
                    t += map[*str – ‘A’];
                    str++;
            }
            return t;
    }

    int main(void)
    {
            int i;
            long long n;
            unsigned ans = 0;
            freopen("namenum.in", "r", stdin);
            freopen("namenum.out", "w", stdout);
            fp = fopen("dict.txt", "r");
            assert(fp != NULL);
            scanf("%lld", &n);
            while(fscanf(fp, "%s", str) == 1){
                    if(change(str) == n){
                            printf("%s\n", str);
                            ans++;
                    }
            }
            if(ans == 0){
                    printf("NONE\n");
            }
            return 0;
    }

  • USACO 1.2.2 Transformations

      这题没什么别的巧,就是硬搜,我犯的唯一一个错误就是使用了strcmp来进行判断,但是又没有给字符串设置结尾标识’\0’,幸运的是我在提交前查出来了,所以还是一次性提交成功,哈哈 !代码如下:

    /
    LANG:
    C

    ID: logoo2
    PROG:
    transform

    /
    #include <stdio.h>
    #include
    <string.h>
    typedef struct{
            char map[10][11];
    }pic;
    int n;
    pic map, end;

    pic change1(pic
    box)
    {
            int i, j;
            pic
    tmp;
            for(i = 0; i < n; i++){
                    for(j = 0; j < n;
    j++){
                            tmp.map[j][n – 1 –
    i] = box.map[i][j];
                    }
                    /
                    mistack
    1:

                      忘记增加结束标识
                    
    /
                    tmp.map[i][n] = ‘\0’;
            }
            return tmp;
    }

    int com(pic a, pic b)
    {
            int i;
            for(i = 0; i < n;
    i++){
                    if(strcmp(a.map[i],
    b.map[i]) != 0){
                            return 1;
                    }
            }
            return 0;
    }

    pic
    change2(pic box)
    {
            int i,
    j;
            pic tmp;
            for(i =
    0; i < n; i++){
                    for(j = 0; j < n;
    j++){
                            tmp.map[i][n – 1 –
    j] = box.map[i][j];
                    }
                    tmp.map[i][n] =
    ‘\0’;
            }
            return tmp;
    }

    int main(void)
    {
            int i;
            freopen("transform.in", "r", stdin);
            freopen("transform.out", "w", stdout);
            scanf("%d", &n);
            for(i = 0; i < n;
    i++){
                    scanf("%s\n", map.map[i]);
            }
            for(i = 0; i < n;
    i++){
                    scanf("%s\n", end.map[i]);
            }
            if(com(change1(map), end) == 0){
                    printf("1\n");
            }else if(com(change1(change1(map)), end) == 0){
                    printf("2\n");
            }else if(com(change1(change1(change1(map))), end) == 0){
                    printf("3\n");
            }else if(com(change2(map), end) == 0){
                    printf("4\n");
            }else if((com(change1(change2(map)), end) == 0)
    ||
                    (com(change1(change1(change2(map))), end) == 0)
    ||
                    (com(change1(change1(change1(change2(map)))), end) ==
    0)){
                    printf("5\n");
            }else if(com(map,
    end) == 0){
                    printf("6\n");
            }else{
                    printf("7\n");
            }
            return 0;
    }