SRM 600 DIV1

A

 按位讨论,取最小值;

B

 数据范围不大,首先要确定枚举角度;

 状压枚举palindromes的列比较科学;

 列确定后,目标就是求获得rcnt行的最小代价:

  dp[i][cnt]表示扫描到第i行,已经有cnt个满足要求的最小代价;

 根据对称性,只要扫描n/2行,而从第i行获得j个增益的代价cost[i][j],可以另外处理:

  当考虑cost[i][j]时,根据对称性,实际是考虑2行(i,n-i),从这2行获得增益的情况只有3种:0,1,2,

  然后,讨论每种情况下的代价:

    0, 只需保证列满足要求;

    1, 任一行满足要求,取最小值;

    2, 2行 同时满足要求;

  然后各种特判...

  1 #include <vector>

  2 #include <list>

  3 #include <map>

  4 #include <set>

  5 #include <deque>

  6 #include <stack>

  7 #include <bitset>

  8 #include <algorithm>

  9 #include <functional>

 10 #include <numeric>

 11 #include <utility>

 12 #include <sstream>

 13 #include <iostream>

 14 #include <iomanip>

 15 #include <cstdio>

 16 #include <cmath>

 17 #include <cstdlib>

 18 #include <ctime>

 19 #include <cstring>

 20 using namespace std;

 21 #define maxn (1<<14)

 22 #define INF 4000

 23 #define rep(i,n) for(int i=0 ; i<(n) ; i++ )

 24 class PalindromeMatrix {

 25 public:

 26     int minChange(vector <string>, int, int);

 27 };

 28 vector<int> valid;

 29 int bit[maxn],n,m;

 30 int check(int mask,int len) {

 31     rep (i,len/2) {

 32         int p = mask&(1<<i);

 33         int q = mask&(1<<(len-i-1));

 34         if (p!=q) return 0;

 35     }

 36     return 1;

 37 }

 38 void init() {

 39     rep (i,maxn) {

 40         if ((i<<1)<maxn)bit[i<<1] = bit[i];

 41         if ((i<<1|1)<maxn)bit[i<<1|1] = bit[i]+1;

 42     }

 43     rep (i,(1<<m)) if (check(i,m)) valid.push_back(i);

 44 }

 45 int dp[15][15],cost[15][3];

 46 void init(vector<string> A,int mask) {

 47     rep (i,15) rep (j,15) dp[i][j]=INF;

 48     rep (i,15) rep (j,3) cost[i][j]=INF;

 49     rep (i,n/2) {

 50         string s1 = A[i];

 51         string s2 = A[n-1-i];

 52     //    cout<<"s1:"<<s1<<endl;

 53     //    cout<<"s2:"<<s2<<endl;

 54         int res = 0;

 55         // r=0

 56         rep (j,m) if (mask&(1<<j)) {

 57             if (s1[j]!=s2[j]) res++;

 58         }

 59         cost[i][0]=res;

 60         // r=2

 61         res = 0;

 62         //printf("cal:cost[%d][2]\n",i);

 63         rep (j,m/2) {

 64             int a=j,b=m-1-j;

 65             if ( (mask&(1<<a)) || (mask&(1<<b)) ) {

 66         //        printf("s1[%d]:%c s1[%d]:%c s2[%d]:%c s2[%d]:%c\n",a,s1[a],b,s1[b],a,s2[a],b,s2[b]);

 67                 int tmp = (s1[a]+s2[a]+s1[b]+s2[b]-4*(int)'0');

 68                 tmp = min(tmp,4-tmp);

 69                 res += tmp;

 70             }else {

 71                 if (s1[a]!=s1[b]) res++;

 72                 if (s2[a]!=s2[b]) res++;

 73             }

 74         }

 75         cost[i][2]=res;

 76         // r=1,s1

 77         res=0;

 78         rep (j,m/2) {

 79             int a=j,b=m-1-j;

 80             if (s1[a] != s1[b]) {

 81                 if ( (mask&(1<<a)) && (mask&(1<<b)) ) {

 82                     int tmp = s1[a]+s1[b]+s2[a]+s2[b]-4*'0';

 83                     res += min(tmp,4-tmp);

 84                 } else res ++;

 85             } else {

 86                 if ( (mask&(1<<a)) && (mask&(1<<b)) ) {

 87                     int tmp = s1[a]+s1[b]+s2[a]+s2[b]-4*'0';

 88                     res += min(tmp,4-tmp);

 89                  } else if ( (mask&(1<<a)) ) {

 90                     res += (s1[a]!=s2[a]);

 91                  } else if ( (mask&(1<<b)) ) {

 92                     res += (s1[b]!=s2[b]);

 93                  }

 94             }

 95         }

 96         cost[i][1]=res;

 97         // r=1,s2

 98         res=0;

 99         rep (j,m/2) {

100             int a=j,b=m-1-j;

101             if (s2[a] != s2[b]) {

102                 if ( (mask&(1<<a)) && (mask&(1<<b)) ) {

103                     int tmp = s1[a]+s1[b]+s2[a]+s2[b]-4*'0';

104                     res += min(tmp,4-tmp);

105                 } else res ++;

106             } else {

107                 if ( (mask&(1<<a)) && (mask&(1<<b)) ) {

108                     int tmp = s1[a]+s1[b]+s2[a]+s2[b]-4*'0';

109                     res += min(tmp,4-tmp);

110                  } else if ( (mask&(1<<a)) ) {

111                     res += (s1[a]!=s2[a]);

112                  } else if ( (mask&(1<<b)) ) {

113                     res += (s1[b]!=s2[b]);

114                  }

115             }

116         }

117         cost[i][1]=min(cost[i][1],res);

118     }

119 }

120 void PrintMask(int mask) {//printf("var:%d mask:",mask);

121     while (mask) {

122     //    printf("%d",mask&1?1:0);

123         mask>>=1;

124     }//printf("\n");

125 }

126 int solv(vector<string> A,int nr,int nc) {

127     int ans = INF;

128     rep (s,(1<<m)) if (bit[s]==nc) {

129         PrintMask(s);

130         init(A,s);

131         dp[0][0] = 0;

132         rep (i,n/2) rep (j,nr+1)

133         if (dp[i][j]!=INF) {

134             rep (k,3) {

135                 int nxtj = min(nr,k+j);

136                 dp[i+1][nxtj] = min(dp[i+1][nxtj],dp[i][j]+cost[i][k]);

137             }

138         }

139         ans = min(ans,dp[n/2][nr]);

140     }

141     return ans;

142 }

143 int PalindromeMatrix::minChange(vector <string> A, int nr, int nc) {

144     init();

145     n = A.size();

146     m = A[0].size();

147     int ans= solv(A,nr,nc);

148     return ans;

149 }
View Code

 

C

 刚开始想按b递增考虑,每加入一条线时的增加数应该很好算,后来发现情况非常复杂,很难发现结论.

 题解的结论是从交点个数得到的.

 尝试证明一下:

  加入一条直线时,每产生一个交点,就划分出一个新的区域,最后想象无穷远处有条封闭的边界,与延时到无限远的直线构成新的区域,

  所以结论为  1 + 不同的交点个数.

 

 1 #include <vector>

 2 #include <list>

 3 #include <map>

 4 #include <set>

 5 #include <deque>

 6 #include <stack>

 7 #include <bitset>

 8 #include <algorithm>

 9 #include <functional>

10 #include <numeric>

11 #include <utility>

12 #include <sstream>

13 #include <iostream>

14 #include <iomanip>

15 #include <cstdio>

16 #include <cmath>

17 #include <cstdlib>

18 #include <ctime>

19 

20 using namespace std;

21 

22 class LotsOfLines {

23 public:

24     long long countDivisions(int, int);

25 };

26 int gcd(int a,int b) {

27     if (b==0) return a;

28     return gcd(b,a%b);

29 }

30 long long sum[1201][1201];

31 long long LotsOfLines::countDivisions(int A, int B) {

32     long long ans = 1;

33     A-- , B--;

34     for (int q=1 ; q<=A ; q++ ) {

35         for (int p=1 ; p<=B ; p++ ) {

36             int x = gcd(p,q)==1?1:0;

37             sum[q][p] = sum[q-1][p] + sum[q][p-1] - sum[q-1][p-1] + x;

38         }

39     }

40     for (int a=0 ; a<=A ; a++ ) {

41         for (int b=0 ; b<=B ; b++ ) {

42             ans ++;

43             if (a)

44                 ans += 1 + sum[a][b] + sum[a][B-b];

45         }

46     }

47     return ans;

48 }

49 

50 

51 //Powered by [KawigiEdit] 2.0!
View Code

 

 

你可能感兴趣的:(div)