SRM 513 2 1000CutTheNumbers(状态压缩)

SRM 513 2 1000CutTheNumbers


Problem Statement

Manao has a board filled with digits represented as String[] board. The j-th character of the i-th element of board represents the digit written in cell in row i, column j of the board. The rows are numbered from top to bottom and the columns are numbered from left to right.

Manao is going to cut it into several non-overlapping fragments. Each of the fragments will be a horizontal or vertical strip containing 1 or more elements. A strip of length N can be interpreted as an N-digit number in base 10 by concatenating the digits on the strip in order. The horizontal strips are read from left to right and the vertical strips are read from top to bottom. The picture below shows a possible cutting of a 4x4 board: 

The sum of the numbers on the fragments in this picture is 493 + 7160 + 23 + 58 + 9 + 45 + 91 = 7879.

Manao wants to cut the board in such a way that the sum of the numbers on the resulting fragments is the maximum possible. Compute and return this sum.

Definition

  • ClassCutTheNumbers
  • MethodmaximumSum
  • Parametersvector<string>
  • Returnsint
  • Method signatureint maximumSum(vector<string> board)

(be sure your method is public)

Limits

  • Time limit (s)2.000
  • Memory limit (MB)64

Notes

  • The numbers on the cut strips are allowed to have leading zeros. See example #2 for details.

Constraints

  • board will contain between 1 and 4 elements, inclusive.
  • board[0] will be between 1 and 4 characters long, inclusive.
  • Each element of board will be of the same length as board[0].
  • Each character in board will be a decimal digit (‘0‘-‘9‘).

Test cases

    • board{"123",
       "312"}

    Returns435

    Manao can cut out both rows in whole, obtaining 123 + 312 = 435. He also could cut the columns one by one for a total of 66, or cut the first column and the residual rows one by one, obtaining 13 + 23 + 12 = 48, or even cut out single elements, but would not get a better sum.

  1.  
    • board{"99",
       "11"}

    Returns182

    It‘s better to cut out the whole columns.

  2.  
    • board{"001",
       "010",
       "111",
       "100"}

    Returns1131

    The numbers on the strips may have leading zeros. Cutting the columns in whole, Manao obtains 0011 + 0110 + 1010 = 1131.

  3.  
    • board{ "8" }

    Returns8



This problem statement is the exclusive and proprietary property of TopCoder, Inc. Any unauthorized use or reproduction of this information without the prior written consent of TopCoder, Inc. is strictly prohibited. (c)2003, TopCoder, Inc. All rights reserved.

你可以认为0的话,就是向左连,1的话就是向下连。

然后状态压缩一下。枚举所有的状态即可。

  1 #include <cstdio>
  2 #include <cmath>
  3 #include <cstring>
  4 #include <ctime>
  5 #include <iostream>
  6 #include <algorithm>
  7 #include <set>
  8 #include <vector>
  9 #include <sstream>
 10 #include <typeinfo>
 11 #include <fstream>
 12
 13 using namespace std;
 14 const int inf = 0x3f3f3f3f ;
 15 int n , m ;
 16 int maxn ;
 17 int path[5] ;
 18 vector<int> b[10] ;
 19 class CutTheNumbers {
 20     public:
 21     int maximumSum(vector<string> board) {
 22         n = board.size () ;
 23         m = board[0].size () ;
 24         for (int i = 0 ; i < n ; i ++) b[i].clear () ;
 25         for (int i = 0 ; i < n ; i ++) {
 26             for (int j = 0 ; j < m ; j ++) {
 27                 b[i].push_back( board[i][j] - ‘0‘ );
 28             }
 29         }
 30         maxn = - inf ;
 31         dfs (0) ;
 32         return maxn ;
 33     }
 34
 35     void dfs (int dep) {
 36         if (dep == n) {
 37             solve () ;
 38             return ;
 39         }
 40         for (int i = 0 ; i < (1 << m) ; i ++) {
 41            path[dep] = i ;
 42            dfs (dep + 1) ;
 43         }
 44     }
 45
 46     void solve () {
 47         bool map[5][5] ;
 48         int ans = 0 ;
 49         memset (map , 0 , sizeof(map) ) ;
 50
 51         for (int i = 0 ; i < n ; i ++) {
 52             int j = 0 ;
 53             int tmp = path[i] ;
 54             while (tmp) {
 55                 map[i][j ++] = tmp & 1 ;
 56                tmp>>= 1 ;
 57             }
 58             reverse (map[i] , map[i] + m) ;
 59         }
 60
 61         bool mark[5][5] ;
 62         memset (mark , 0 , sizeof(mark) ) ;
 63
 64         for (int i = 0 ; i < n ; i ++) {
 65             for (int j = 0 ; j < m ; j ++) {
 66                 if (!mark[i][j]) {
 67                     int tmp = 0 ;
 68                     if (!map[i][j]) {
 69                         for (int k = j ; k < m && !map[i][k] ; k ++) {
 70                             mark[i][k] = 1 ;
 71                             tmp = tmp * 10 + b[i][k] ;
 72                         }
 73                     }
 74                     else {
 75                         for (int k = i ; k < n && map[k][j] ; k ++) {
 76                             mark[k][j] = 1 ;
 77                             tmp = tmp * 10 + b[k][j] ;
 78                         }
 79                     }
 80                     ans += tmp ;
 81                 }
 82             }
 83         }
 84         maxn = max (maxn , ans) ;
 85     }
 86
 87
 88 };
 89
 90 // CUT begin
 91 ifstream data("CutTheNumbers.sample");
 92
 93 string next_line() {
 94     string s;
 95     getline(data, s);
 96     return s;
 97 }
 98
 99 template <typename T> void from_stream(T &t) {
100     stringstream ss(next_line());
101     ss >> t;
102 }
103
104 void from_stream(string &s) {
105     s = next_line();
106 }
107
108 template <typename T> void from_stream(vector<T> &ts) {
109     int len;
110     from_stream(len);
111     ts.clear();
112     for (int i = 0; i < len; ++i) {
113         T t;
114         from_stream(t);
115         ts.push_back(t);
116     }
117 }
118
119 template <typename T>
120 string to_string(T t) {
121     stringstream s;
122     s << t;
123     return s.str();
124 }
125
126 string to_string(string t) {
127     return "\"" + t + "\"";
128 }
129
130 bool do_test(vector<string> board, int __expected) {
131     time_t startClock = clock();
132     CutTheNumbers *instance = new CutTheNumbers();
133     int __result = instance->maximumSum(board);
134     double elapsed = (double)(clock() - startClock) / CLOCKS_PER_SEC;
135     delete instance;
136
137     if (__result == __expected) {
138         cout << "PASSED!" << " (" << elapsed << " seconds)" << endl;
139         return true;
140     }
141     else {
142         cout << "FAILED!" << " (" << elapsed << " seconds)" << endl;
143         cout << "           Expected: " << to_string(__expected) << endl;
144         cout << "           Received: " << to_string(__result) << endl;
145         return false;
146     }
147 }
148
149 int run_test(bool mainProcess, const set<int> &case_set, const string command) {
150     int cases = 0, passed = 0;
151     while (true) {
152         if (next_line().find("--") != 0)
153             break;
154         vector<string> board;
155         from_stream(board);
156         next_line();
157         int __answer;
158         from_stream(__answer);
159
160         cases++;
161         if (case_set.size() > 0 && case_set.find(cases - 1) == case_set.end())
162             continue;
163
164         cout << "  Testcase #" << cases - 1 << " ... ";
165         if ( do_test(board, __answer)) {
166             passed++;
167         }
168     }
169     if (mainProcess) {
170         cout << endl << "Passed : " << passed << "/" << cases << " cases" << endl;
171         int T = time(NULL) - 1436409000;
172         double PT = T / 60.0, TT = 75.0;
173         cout << "Time   : " << T / 60 << " minutes " << T % 60 << " secs" << endl;
174         cout << "Score  : " << 1000 * (0.3 + (0.7 * TT * TT) / (10.0 * PT * PT + TT * TT)) << " points" << endl;
175     }
176     return 0;
177 }
178
179 int main(int argc, char *argv[]) {
180     cout.setf(ios::fixed, ios::floatfield);
181     cout.precision(2);
182     set<int> cases;
183     bool mainProcess = true;
184     for (int i = 1; i < argc; ++i) {
185         if ( string(argv[i]) == "-") {
186             mainProcess = false;
187         } else {
188             cases.insert(atoi(argv[i]));
189         }
190     }
191     if (mainProcess) {
192         cout << "CutTheNumbers (1000 Points)" << endl << endl;
193     }
194     return run_test(mainProcess, cases, argv[0]);
195 }
196 // CUT end

时间: 2024-12-19 08:35:44

SRM 513 2 1000CutTheNumbers(状态压缩)的相关文章

SRM 628 DIV2 1000 CandleTimerEasy 状态压缩+DFS

题意:给你一个树型蜡烛,你可以从1个或多个叶子开始点蜡烛,问你能使蜡烛烧完以后能得到时间的个数. 解题思路:状态压缩枚举DFS, 解题代码: 1 // BEGIN CUT HERE 2 /* 3 4 */ 5 // END CUT HERE 6 #line 7 "CandleTimerEasy.cpp" 7 #include <cstdlib> 8 #include <cctype> 9 #include <cstring> 10 #include

状态压缩DP SRM 667 Div1 250

题意:给n个01串,设计一种顺序,使得每次新出现的1的个数^2和最小 分析:比赛时不知道是div1的题,以为暴力贪心可以过,结果被hack掉了.题解说没有充分的证明使用贪心是很有风险的,正解是用状态压缩DP,详细解释. 收获:爆零还能涨分,TC真奇怪. 代码: int dp[(1<<20)+10]; int a[55]; class OrderOfOperations { public: int minTime( vector <string> s ) { int n = s.si

胜利大逃亡(续)(状态压缩bfs)

胜利大逃亡(续) Time Limit: 4000/2000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others) Total Submission(s): 7357    Accepted Submission(s): 2552 Problem Description Ignatius再次被魔王抓走了(搞不懂他咋这么讨魔王喜欢)……这次魔王汲取了上次的教训,把Ignatius关在一个n*m的地牢里,并在地牢的某些地方安装了带

uva 818(dfs+图+状态压缩)

题意:有n个环,编号从1到n,给出了一些环环相扣的情况,比如给a和b表示a和b两个环的扣在一起的,每个环都是可以打开的,问最少打开多少个环,然后再扣好,可以让所有的环成为一条链. 题解:状态压缩把所有的打开环的情况枚举出来,然后拿去判断是否成立,更新打开环后的图g[i][j],和每个点的度数,不成立有三种情况,1.计算没有打开的环的度数,如果大于2说明不会有链,2.把没有打开环拿去dfs,访问过就vis[i]++,如果vis[i]>=2说明存在环,3.如果打开的环数num + 1小于链的数量,说

POJ 3254 Corn Fields 状态压缩DP (C++/Java)

http://poj.org/problem?id=3254 题目大意: 一个农民有n行m列的地方,每个格子用1代表可以种草地,而0不可以.放牛只能在有草地的,但是相邻的草地不能同时放牛, 问总共有多少种方法. 思路: 状态压缩的DP. 可以用二进制数字来表示放牧情况并判断该状态是否满足条件. 这题的限制条件有两个: 1.草地限制. 2.相邻限制. 对于草地限制,因为输入的时候1是可以种草地的. 以"11110"草地分析,就只有最后一个是不可以种草的.取反后得00001  .(为啥取反

uva 11195 Another queen (用状态压缩解决N后问题)

题目链接:http://uva.onlinejudge.org/index.php?option=com_onlinejudge&Itemid=8&page=show_problem&problem=2136 Problem A Another n-Queen Problem I guess the n-queen problem is known by every person who has studied backtracking. In this problem you s

dp状态压缩

dp状态压缩 动态规划本来就很抽象,状态的设定和状态的转移都不好把握,而状态压缩的动态规划解决的就是那种状态很多,不容易用一般的方法表示的动态规划问题,这个就更加的难于把握了.难点在于以下几个方面:状态怎么压缩?压缩后怎么表示?怎么转移?是否具有最优子结构?是否满足后效性?涉及到一些位运算的操作,虽然比较抽象,但本质还是动态规划.找准动态规划几个方面的问题,深刻理解动态规划的原理,开动脑筋思考问题.这才是掌握动态规划的关键. 动态规划最关键的要处理的问题就是位运算的操作,容易出错,状态的设计也直

HDU3001(KB2-J 状态压缩dp)

Travelling Time Limit: 6000/3000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)Total Submission(s): 8103    Accepted Submission(s): 2642 Problem Description After coding so many days,Mr Acmer wants to have a good rest.So travelling is

2017盛大游戏杯 零件组装(状态压缩DP之巧妙枚举子集)

题目链接:2017盛大游戏杯 零件组装 题意: 有n个零件,给你相邻关系和排斥关系,每两块零件组装起来有一个代价,问最少的代价总和是多少. 题解: 考虑状态压缩,dp[i]表示i这个集合为一个零件块. 那么要枚举一下i的子集.O(3^n). 先要预处理一下每个集合的排斥个数和相邻个数,然后容斥一下就可以了. 1 #include<bits/stdc++.h> 2 #define mst(a,b) memset(a,b,sizeof(a)) 3 #define F(i,a,b) for(int