zoukankan      html  css  js  c++  java
  • USACO 3.3

    3.3开始的文字介绍是欧拉通路和欧拉回路。类似于小时候学过的一笔画问题。介绍里伪代码写的很清晰,几乎照着拍就可以A题。

    Riding The Fences:TEXT里的例题,欧拉路径。TEXT里说因为递归的层数比较深,所以要自己定义栈。我这里就用循环写了。其实递归也可以过。

     1 # include <stdio.h>
     2 # include <string.h>
     3 
     4 
     5 int g[510][510], stack[110], top ;
     6 int degree[510] ;
     7 int EulerCircuit[1100] ;
     8 
     9 
    10 void FindEuler(int s)
    11 {
    12     int i, ec = 0 ;
    13     top = 0 ;
    14     stack[top++] = s ;
    15     while (top)
    16     {
    17         s = stack[--top] ;
    18         if (degree[s] == 0){
    19             EulerCircuit[ec++] = s ;
    20             continue ;
    21         }
    22         //else
    23         stack[top++] = s ;
    24         for (i = 1 ; i <= 500 ; i++)if (g[s][i])
    25         {
    26             g[s][i]--, g[i][s]--, degree[s]--, degree[i]-- ;
    27             stack[top++] = i ;
    28             break ;
    29         }
    30     }
    31 }
    32 
    33 
    34 int main ()
    35 {
    36     int a, b, i, f ;
    37     freopen ("fence.in", "r", stdin) ;
    38     freopen ("fence.out", "w", stdout) ;
    39     while (~scanf ("%d", &f))
    40     {
    41         memset (g, 0, sizeof(g)) ;
    42         memset (degree, 0, sizeof(degree)) ;
    43         for (i = 0 ; i < f ; i++)
    44             scanf ("%d%d", &a, &b), g[a][b]++, g[b][a]++, degree[a]++, degree[b]++ ;
    45         for (i = 1 ; i <= 500 ; i++) if (degree[i]%2==1) break ;
    46         if (i > 500) i = 1 ;
    47         FindEuler(i) ;
    48         for (i = f ; i >= 0 ; i--)
    49             printf ("%d
    ", EulerCircuit[i]) ;
    50     }
    51     return 0 ;
    52 }
    View Code

    Shopping Offers:一个比较简单但是写起来很复杂的dp,要开5个维度的数组。。。物品数其实不超过5个- -。我用dfs+记忆化写的。

     1 # include <stdio.h>
     2 # include <string.h>
     3 
     4 
     5 int vv[1010] ;
     6 int idx[110], num[110], prc[110], s ;
     7 int c[510], k[510];
     8 int cs[10], ks[10], ps[10], b ;
     9 int dp[6*6*6*6*6] ;
    10 int INF = 0x0f0f0f0f ;
    11 
    12 
    13 int xy(int a[])
    14 {
    15     int rtn = 0, i ;
    16     for (i = 0 ; i < b ; i++)
    17         rtn = rtn * 6 + a[i] ;
    18     return rtn ;
    19 }
    20 
    21 
    22 int min(int a, int b){return a<b?a:b;}
    23 
    24 
    25 int dfs (int a[])
    26 {
    27     int i, j, rtn = INF, flag, pos ;
    28     if (dp[xy(a)] != -1) return dp[xy(a)] ;
    29     
    30     for (i = 0 ; i < b ; i++) if (a[i] != 0)
    31     {
    32         a[i] -- ;
    33         rtn = min(rtn, dfs (a) + ps[i]) ;
    34         a[i] ++ ;
    35     }
    36     
    37     for (i = 0 ; i < s ; i++)
    38     {
    39         flag = 0 ;
    40         for (j = idx[i] ; j < idx[i]+num[i] ; j++)
    41         {
    42             pos = vv[c[j]] ;
    43             if (pos == -1) flag = 1 ;
    44             else
    45             {
    46                 a[pos] -= k[j] ;
    47                 if (a[pos] < 0) flag = 1 ;
    48             }
    49         }
    50         if (flag == 0)
    51             rtn = min(rtn, dfs (a)+prc[i]) ;
    52         for (j = idx[i] ; j < idx[i]+num[i] ; j++)
    53         {
    54             pos = vv[c[j]] ;
    55             if (pos != -1)
    56                 a[pos] += k[j] ;
    57         }
    58 
    59     }
    60     return dp[xy(a)] = rtn ;
    61 }
    62 
    63 
    64 int main ()
    65 {
    66     int cc, i, j, n ;
    67     freopen ("shopping.in", "r", stdin) ;
    68     freopen ("shopping.out", "w", stdout) ;
    69     while (~scanf ("%d", &s))
    70     {
    71         for (i = 0, cc = 0 ; i < s ; i++)
    72         {
    73             idx[i] = cc ;
    74             scanf ("%d", &n) ;
    75             num[i] = n ;
    76             for (j = 0 ; j < n; j++)
    77                 scanf ("%d%d", &c[cc], &k[cc]), cc++ ;
    78             scanf ("%d", &prc[i]) ;
    79         }
    80         memset (vv, -1, sizeof (vv)) ;
    81         scanf ("%d", &b) ;
    82         for (i = 0 ;i < b ; i++)
    83         {
    84             scanf ("%d%d%d", &cs[i], &ks[i], &ps[i]) ;
    85             vv[cs[i]] = i ;
    86         }
    87         memset (dp, -1, sizeof (dp)) ;
    88         dp[0] = 0 ;
    89         printf ("%d
    ", dfs (ks)) ;
    90     }
    91     return 0 ;
    92 }
    View Code

    Camelot:本节最复杂最难搞的题了。本质是bfs,但是要想一下复杂度。基本想法是这样:地图大概1000个点,先枚举终点。对于每个终点,可以假设有1个骑士带王走,其他的不带。计算出每个骑士带王和不代王需要花费的步数,再枚举每个骑士带王走的情况(注意还要考虑王自己走到终点的情况)。计算每个骑士带王的时候,可以枚举骑士和王重合点。但是这样一来,要枚举终点、重合点以及骑士,复杂度是O(r*c*KnightNumber*r*c),大概是1000^3,要超时了。可以考虑王和骑士重合点不超过王所在位置±2的范围内(也就是25个点),因此重合点可以被认为是常数,复杂度降到O(r*c*Knight*25),可做。

    注意大坑:输入是先列数再行数!这里调了一天- -。

      1 # include <stdio.h>
      2 
      3 
      4 #define STEP 2
      5 #define NS ((2*STEP+1)*(2*STEP+1))
      6 int tab[NS+10][2] ;
      7 int ktab[8][2] = {{-2,-1}, {-2,1}, {-1,-2},{-1,2},{1,-2},{1,2},{2,-1},{2,1}} ;
      8 int n, m ;
      9 int nx[1010], ny[1010], kx, ky, cc ;
     10 int end[35][35] ;
     11 int king[30][35][35] ;
     12 int noking[1010], takeking[1010] ;
     13 int INF = 0x0f0f0f0f ;
     14 int q[1010][2] ;
     15 
     16 
     17 int mymax(int a,int b){return a>b?a:b;}
     18 int mymin(int a, int b){return a<b?a:b;}
     19 int myabs(int x){return x<0?-x:x;}
     20 int kingdist(int x, int y){return mymax(myabs(x-kx), myabs(y-ky)) ;}
     21 
     22 
     23 void bfs (int x, int y, int g[35][35])
     24 {
     25     int f, r, i, j, xx, yy ;
     26     for (i = 1 ; i<= n ; i++)
     27         for (j = 1 ; j <= m ; j++)
     28             g[i][j] = INF ;
     29     g[x][y] = 0 ;
     30     q[0][0] = x, q[0][1] = y ;
     31     for (f = 0,r=1 ; f < r ; f++)
     32     {
     33         x = q[f][0], y = q[f][1] ;
     34         for (i = 0 ; i < 8 ; i++)
     35         {
     36             xx = x + ktab[i][0], yy = y + ktab[i][1] ;
     37             if (xx <= 0 || xx > n || yy <= 0 || yy > m) continue ;
     38             if (g[xx][yy] != INF) continue ;
     39             g[xx][yy] = g[x][y] + 1 ;
     40             q[r][0]=xx, q[r][1] = yy, r++ ;
     41         }
     42     }
     43 }
     44 
     45 
     46 int gao(int ex, int ey)
     47 {
     48     int xx, yy, sum, ans ;
     49     int i, j ;
     50     bfs (ex, ey, end) ;
     51 
     52     for (i = 0 ; i < NS ; i++){
     53         xx = kx + tab[i][0], yy = ky + tab[i][1] ;
     54         if (xx >= 1 && xx <= n && yy >= 1 && yy <= m)
     55             bfs (xx, yy, king[i]) ;
     56     }
     57 
     58 
     59     for (i = 0 ; i < cc ; i++)
     60     {
     61         noking[i] = end[nx[i]][ny[i]] ;
     62         takeking[i] = INF ;
     63         for (j = 0 ; j < NS ; j++){
     64             xx = kx + tab[j][0], yy = ky + tab[j][1] ;
     65             if (xx >= 1 && xx <= n && yy >= 1 && yy <= m)
     66                 takeking[i] = mymin(    takeking[i], 
     67                                       king[j][nx[i]][ny[i]] + kingdist(xx,yy)
     68                                                               + end[xx][yy]) ;
     69         }
     70     }
     71     
     72     sum = 0;
     73     ans = kingdist(ex, ey) ;
     74     for (i = 0 ; i < cc ; i++)
     75         ans += noking[i], sum += noking[i] ;
     76 
     77     for (i = 0 ; i < cc ; i++)
     78         ans = mymin(ans, sum - noking[i] + takeking[i]) ;
     79 
     80     return ans ;
     81 }
     82 
     83 
     84 int main ()
     85 {
     86     char xchar ;
     87     int yint, i, j, ans ;
     88     freopen ("camelot.in", "r", stdin) ;
     89     freopen ("camelot.out", "w", stdout) ;
     90     
     91     scanf ("%d %d%*c", &m, &n) ;
     92     scanf ("%c %d%*c", &xchar, &yint) ;
     93     ans = 0 ;
     94     for (i = -STEP ; i <= STEP ; i++)
     95         for (j = -STEP ; j<= STEP ; j++)
     96             tab[ans][0] = i, tab[ans++][1] = j ;
     97     kx = xchar-'A'+1, ky = yint ;
     98     cc = 0 ;
     99 
    100     while (~scanf ("%c %d%*c", &xchar, &yint))
    101         nx[cc] = xchar-'A'+1, ny[cc] = yint, cc++ ;
    102     
    103     ans = INF ;
    104     for (i = 1 ; i <= n ; i++)
    105         for (j = 1 ; j <= m ; j++)
    106             ans = mymin(ans, gao(i,j)) ;
    107 
    108     printf ("%d
    ", ans) ;
    109     return 0 ;
    110 }
    View Code

    Home on the Range:这题是非常水的题了。可以开一个数组num[i][j]表示从左上角到(i,j)这个矩形区域内1的个数。从左上到右下num[i][j]可以利用前面的结果O(1)求出:num[i][j] = num[i-1][j]+num[i][j-1]-num[i-1][j-1]。然后枚举每一个正方形,通过num[i][j]也可以O(1)求出正方形内1的个数,就可以拿来判断该形状里是否有坏点。这种计算矩形内数字和的方法非常经典。

     1 # include <stdio.h>
     2 
     3 
     4 char gg[300][300] ;
     5 int g[300][300] ;
     6 int ans[300] ;
     7 
     8 int main ()
     9 {
    10     int i, j, len, p, num ;
    11     freopen ("range.in", "r", stdin) ;
    12     freopen ("range.out", "w", stdout) ;
    13     
    14     while (~scanf ("%d", &p))
    15     {
    16         for (i = 0 ; i < 300 ; i++) ans[i] = 0 ;
    17         for(i = 1 ; i <= p ; i++)
    18             scanf("%s", gg[i]+1) ;
    19         for (i =1 ; i <= p ;i++)
    20             for (j = 1 ; j <= p ;j++)
    21                 g[i][j] = g[i-1][j]+g[i][j-1]-g[i-1][j-1] + (gg[i][j]-'0') ;
    22 
    23         for (i = 1 ; i <= p ; i++)
    24             for (j = 1 ;j <= p ; j++)
    25             {
    26                 for (len = 2 ; len <= p-i+1 && len <= p-j+1 ; len++)
    27                 {
    28                     num = g[i+len-1][j+len-1]+g[i-1][j-1]-g[i+len-1][j-1]-g[i-1][j+len-1] ;
    29                     if (num != len*len) break ;
    30                     ans[len]++ ;
    31                 }
    32             }
    33         for (i = 2 ; i <= p ; i++) if (ans[i] != 0)
    34             printf ("%d %d
    ", i, ans[i]) ;
    35     }
    36     return 0 ;
    37 }
    View Code

    A Game:这题也是比较水的题。很容易想到dp的策略:dp[i][j]表示从第i个数字到第j个数字区域先手最大能拿多少分,通过dp[i+1][j]和dp[i][j-1]可以O(1)算出。需要预处理出sum[i]表示开头到i的和,这样可以O(1)求出任意区间的和。

     1 # include <stdio.h>
     2 # include <string.h>
     3 
     4 
     5 int a[110], sum[110], dp[110][110] ;
     6 int max(int a, int b){return a>b?a:b;}
     7 
     8 
     9 int dfs (int s, int e)
    10 {
    11     int ans1, ans2 ;
    12     if (s == e) return a[s] ;
    13     if (dp[s][e] != -1) return dp[s][e] ;
    14     
    15     ans1 = a[s] + sum[e] - sum[s] - dfs (s+1,e) ;
    16     ans2 = a[e] + sum[e-1] - sum[s-1] - dfs (s, e-1) ;
    17     return dp[s][e] = max(ans1, ans2) ;
    18 }
    19 
    20 
    21 int main()
    22 {
    23     int n , i ;
    24     freopen ("game1.in", "r", stdin) ;
    25     freopen ("game1.out", "w", stdout) ;
    26     while (~scanf ("%d", &n))
    27     {
    28         for (i = 1 ; i <= n; i++)
    29             scanf ("%d", &a[i]), sum[i] = sum[i-1] + a[i] ;
    30         memset (dp, -1, sizeof(dp)) ;
    31         dfs (1,n) ;
    32         printf ("%d %d
    ", dp[1][n], sum[n]-dp[1][n]) ;
    33     }
    34     return 0 ;
    35 }
    View Code
  • 相关阅读:
    AVR单片机教程——PWM调光
    AVR单片机教程——蜂鸣器
    AVR单片机教程——串口接收
    做个别出心裁的圣诞礼物
    电源选择电路的原理
    AVR单片机教程——串口发送
    C++类成员默认初始值
    AVR单片机教程——旋转编码器
    10.Django-form表单
    09.Django-数据库优化
  • 原文地址:https://www.cnblogs.com/lzsz1212/p/3180612.html
Copyright © 2011-2022 走看看