TopCoder SRM 280
SRM 280 - Problem Set & Analysis by lovro can be see here.
The following is my solution, all programs are pass system test.
The Problems
This problem only test all integers less then n, and get the number of those whoes all digits all distinct.
we just need a function to judge if a number's all digits are distinct from each other.
the following are my codes:
string UniqueDigits::toString(int num)
{
int a = num;
int b;
string ret;
while(true)
{
b = a%10;
a = (int)(a/10);
ret.insert((string::size_type)0,1,char(b+'0'));
if(a==0) break;
}
return ret;
}
int UniqueDigits::count(int n)
{
int i,j,k;
int ret = 0;
for(i=1;i<n;i++)
{
string str = toString(i);
//cout<<str<<endl;
bool match = true;
for(j=0;j<str.size();j++)
{
for(k=j+1;k<str.size();k++)
{
if(str[j]==str[k]){
match = false;
break;
}
}
if(match == false) break;
}
if(match) ret++;
}
return ret;
}
To solve this problem , I use vector as stack to calculate two number, one is how many brackets should append left
and the other is how many should append right. the following is my code:
string CompletingBrackets::complete(string text)
{
vector<int> S;
int i;
string ret;
for(i=0;i<text.size();i++)
{
if(text[i]=='['){
S.push_back(0);
}else if(text[i]==']'){
if(S.size() == 0){
S.push_back(1);
continue;
}
if(S.back()==0){
S.pop_back();
}
else S.push_back(1);
}
}
int one = 0;
int zero = 0;
for(i=0;i<S.size();i++){
if(S[i] == 0) zero++;
if(S[i] == 1) one++;
}
cout<<one<<" "<<zero<<endl;
string A,B;
for(i=0;i<zero;i++){
A.insert((string::size_type)0,1,']');
}
for(i=0;i<one;i++){
B.insert((string::size_type)0,1,'[');
}
cout<<A<<" "<<B<<endl;
ret = B + text + A;
return ret;
}
This is the most difficult problem in Div.2. Many people can write the solution, but some test case will make there algorithm exceed time limit.
My algorithm include two function :
first function: give number N, m. find m numbers a1,a2,...,am; a1+a2+...+am = N and a1 >= a2 >= a3 ... >= am
second function : solve the GroupingNumbers problem. In my solution, I search all permutations, and this do not exceed time limit.
Following is my codes:
First Function :
vector<vector<int> >GroupingNumbers::all(int number, int n, int minnum)
{
vector<vector<int> > ret;
vector<int> one;
if(number<minnum) return ret;
if(n==1){
if(number>=minnum){
one.push_back(number);
ret.push_back(one);
return ret;
}else return ret;
}
else{
int i,j;
for(i=minnum;i<=number-n+1;i++){
vector<vector<int> > ret1 = all(number-i,n-1,i);
for(j=0;j<ret1.size();j++){
one = ret1[j];
one.push_back(i);
ret.push_back(one);
}
ret1.clear();
}
}
return ret;
}
Second Function:
double GroupingNumbers::minRange(vector<int> number, int n)
{
vector<vector<int> > All = all(number.size(),n,1);
vector<int> a;
int i,j,k,h;
double minave, maxave;
vector<int> temp;
double ret = 9999999999.9999;
for(i=0;i<number.size();i++) a.push_back(i);
bool end;
do{
for(i=0;i<All.size();i++)
{
k = 0;
minave = 9999999999.9999;
maxave = 0;
end = false;
for(j=0;j<All[i].size();j++){
temp.clear();
for(h=0;h<All[i][j];h++){
temp.push_back(number[a[k]]);
k++;
}
double ave = average(temp);
if(ave>maxave) maxave = ave;
if(ave<minave) minave = ave;
}
if(maxave - minave < ret){
ret = maxave - minave;
if(ret==0) return 0;
cout<<maxave<<" "<<minave<<endl;
}
}
}while(std::next_permutation(a.begin(),a.end()));
return ret;
}
To solve this problem , we have to notice two things:
1. To minimum the GridCut length, we must use the edge of rect
2. Shapes with different area may have same perimeter
I consider three condition :
1. one edge have length of 'width'
2. one egde have length of 'height'
3. one edge < width and one edge < height
Algorithm :
int cutLength(int width, int height, int n)
if n > width*height/2 then
n = width*height - n ; // cut length of one part equals to cut length of the left part
int ret = INT_MAX
for(i=1;i<width;i++)
if n%i == 0 then ret = MIN(ret,i+(int)(n/i))
else
j = (int)(n/i)+1
if(j<height) then
ret = MIN(ret,i+j)
if one edge have length 'width' then calculate cutlength c1
if one edge have length 'height' then calculate cutlength c2
ret = MIN(ret,c1,c2)
return ret;
Code:
int GridCut::cutLength(int width, int height, int n)
{
int area = width*height;
int N = n;
if(2*N>area) N = area - N;
int c = INT_MAX;
int i,j;
if(N==0) return 0;
int cur;
for(i=1;i<width;i++){
if(N%i == 0) c = MIN(c,i+(int)(N/i));
else{
j = (int)(N/i)+1;
c = MIN(c,i+j);
}
}
int r2,q2,c2;
r2 = N%width;
q2 = (int)(N/width);
if(q2<height-1){
if(r2 == 0) c2 = width;
else c2 = width + 1;
}else{
c2 = width + 1 - r2;
}
int r3,q3,c3;
r3 = N%height;
q3 = (int)(N/height);
if(q3<width-1){
if(r3 == 0) c3 = height;
else c3 = height + 1;
}else{
c3 = height + 1 - r3;
}
return MIN(c,MIN(c2,c3));
}