Why isn't my convex hull perimeter calculation working? - c++

Input: set of Points
Output: perimeter of convex hull made from these points
I don't why, but I'm still getting bad perimeter on some inputs (I don't know which inputs).
Can you please tell me if there is something bad im my alghorithm? (or implementation)
#include<iostream>
#include<vector>
#include<algorithm>
#include<cmath>
#include<iomanip>
using namespace std;
struct Point{
int x;
int y;
bool operator<(const Point &p)const
{
return (x<p.x || (x==p.x && y<p.y));
}
};
long long cross(Point A, Point B, Point C)
{
return (B.x-A.x)*(C.y-A.y)-(B.y-A.y)*(C.x-A.x);
}
vector<Point> ConvexHull(vector<Point> P) //Andrew's monotone chain
{
vector<Point> H; //hull
H.resize(2*P.size());
int k=0;
if(P.size()<3) return H;
sort(P.begin(),P.end());
//lower
for(int i=0;i<P.size();i++)
{
while(k>=2 && cross(H[k-2],H[k-1],P[i])<=0)
k--;
H[k]=P[i];
k++;
}
int t=k+1;
//upper
for(int i=P.size()-2; i>=0 ;i--)
{
while(k>=t && cross(H[k-2],H[k-1],P[i])<=0)
k--;
H[k]=P[i];
k++;
}
H.resize(k);
return H;
};
double perimeter(vector<Point> P)
{
double r=0;
for(int i=1;i<P.size();i++)
r+=sqrt(pow(P[i].x-P[i-1].x,2)+pow(P[i].y-P[i-1].y,2));
return r;
}
int main(){
int N;
cin>>N;
vector<Point>P;
P.resize(N);
for(int i=0;i<N;i++)
cin>>P[i].x>>P[i].y;
vector<Point>H;
H=ConvexHull(P);
cout<<setprecision(9)<<perimeter(H)<<endl;
//system("pause");
return 0;
};

Assuming the algorithm is correct, I imagine: You are running on 32 bit and get an integer overflow.

Shouldn't you add the code bellow after the for loop in the perimeter function:
r += sqrt(pow(P[P.size() - 1].x-P[0].x,2)+pow(P[P.size() - 1].y-P[0].y,2));
You want to add the distance between the first and the last point in the convex hull.

Related

Greedy Algorithm implemented in fractional knapsack

#include <iostream>
#include<vector>
#include<algorithm>
using namespace std;
double fractional_knapsack(vector<int>& val,vector<int>& wt,int weight)//vectors of values and their respective weights and max weight are passed as parameter
{
int sz=val.size();
vector<double> ratio(sz); //vector to store ratio of values and weights
for(int i=0;i<sz;i++){
ratio[i]=double(val[i]/wt[i]);
}
sort(ratio.begin(),ratio.end(),greater());
//reverse(ratio.begin(),ratio.end());
double max=0.0;
int j=0;
while(max<=weight&&j<sz){
double(weight[j]);
max=max+(ratio[j]*weight[j]);
}
return max;
}
int main()
{ int max_weight,n;
cin>>n>>max_weight;
vector<int>values;
vector<int>weights;
for(int i=0;i<n;i++){
cin>>values[i];
}
for(int i=0;i<n;i++){
cin>>weights[i];
}
double result=fractional_knapsack(values,weights,max_weight);
cout<<"done/n";
cout<<result;
return 0;
}
D:\COdeBlock Projects\Fractional Knapsack\main.cpp|12|error: missing template arguments before '(' token|
it is compiling in devcpp but program_name.exe is crashing
in the method fractional_knapsack(vector<int>& val,vector<int>& wt,int weight) why we pass vector as refrence.
A quick look at the error message reveal the problem lies with the line
sort(ratio.begin(),ratio.end(),greater());
My guess is that you want
sort(ratio.begin(),ratio.end(),greater<double>());
The sort method expects a comparator. If you look at the doc for greater, there's an example on how to use it.
I got the right code.
#include <iostream>
#include<vector>
#include<algorithm>
using namespace std;
double fractional_knapsack(vector<int>& val,vector<int>& wt,int weight)//vectors of values and their respective weights and max weight are passed as parameter
{
int sz=val.size();
vector<double> ratio(sz); //vector to store ratio of values and weights
for(int i=0;i<sz;i++){
ratio[i]=(val[i]/wt[i]);
}
for(int i=0;i<sz;i++){
for(int j=i+1;j<sz;j++){
if(ratio[i]<ratio[j]){
int temp;
temp=ratio[i];
ratio[i]=ratio[j];
ratio[j]=temp;
temp=val[i];
val[i]=val[j];
val[j]=temp;
temp=wt[i];
wt[i]=wt[j];
wt[j]=temp;
}
}
}
//sort(ratio.begin(),ratio.end(),greater<double>());
// sort(val.begin(),val.end(),greater<int>());
//sort(wt.begin(),wt.end(),greater<int>());
//reverse(ratio.begin(),ratio.end());
double max=0.0;
int j=0;
int quantity_left =weight;
while(wt[j]<=quantity_left&&j<sz){
//double(wt[j]);
max=max+(ratio[j]*wt[j]);
cout<<max<<" ";
quantity_left=quantity_left-wt[j];
j++;
}
if(wt[j]>quantity_left&&j<sz){
max=max+(ratio[j]*quantity_left);
// cout<<max<<" ";
}
return max;
}
int main()
{ int max_weight,n;
cin>>n>>max_weight;
vector<int>values(n);
vector<int>weights(n);
for(int i=0;i<n;i++){
cin>>values[i];
}
for(int i=0;i<n;i++){
cin>>weights[i];
}
double result=fractional_knapsack(values,weights,max_weight);
cout<<result;
return 0;
}

Polynomial Class runs fine in debugger but not when trying to build&run

So I've been trying to solve this problem for some hours but without any succes. I've got a class for Polynomial methods(set/get grade, set/get polynom's coefficients, print polynom, find every y = f(x) for a given set of numbers etc.)
However, the problem is that whenever the grade of the polynom is even, the build&run returns strange values. The debug of it runs prefectly fine. On the other side, whenever the grade is uneven, works perfectly fine for both debug and build&run. I'm thinking the problem is somewhere at dinamically allocated memory. Here's the code. Thanks
main.cpp
#include "poly_header.h"
int main()
{
Poly p;
p.AfisareValori();
return 0;
}
poly_header.h
#include <iostream>
#include <math.h>
using namespace std;
class Poly
{
private:
int grad;
int* coeficienti;
int a;
int b;
int dx;
public:
Poly();
void SetGrad();
int GetGrad();
void SetCoef();
void GetCoef();
void SetPolyn();
void PrintPoly();
void SetInterval();
void SetDistanta();
void AfisareValori();
~Poly();
};
poly_functions.cpp
#include "poly_header.h"
Poly::Poly()
{
this->grad = 0;
this->coeficienti = new int[0];
}
Poly::~Poly()
{
delete coeficienti;
}
void Poly::SetGrad()
{
int n;
cout<<"Introduceti gradul dorit al polinomului: ";
cin>>n;
this->grad = n;
}
int Poly::GetGrad()
{
cout<<"\n";
return this->grad;
}
void Poly::SetCoef()
{
int n;
this->coeficienti = new int[this->grad];
for(int i = 0; i <= this->grad; i++){
cout<<"Introduceti coeficientul "<<i<<" :";
cin>>this->coeficienti[i];
cout<<"\n";
}
}
void Poly::GetCoef()
{
cout<<"\n";
for(int i = 0; i <= this->grad; i++)
cout<<"Coeficientul asociat termenului x^"<<i<<" este:"<<this->coeficienti[i]<<"\n";
}
void Poly::SetPolyn()
{
SetGrad();
SetCoef();
}
void Poly::PrintPoly()
{
SetPolyn();
for(int i = grad; i >= 0; i--){
if(i == 0){
cout<<coeficienti[i];
break;
}
cout<<coeficienti[i]<<"*X^"<<i<<" + ";
}
}
void Poly::SetInterval()
{
int a,b;
cout<<"Introduceti capatul din stanga al intervalului: ";
cin>>a;
this->a = a;
cout<<"\n";
cout<<"Introduceti capatul din dreapta al intervalului: ";
cin>>b;
this->b = b;
cout<<"\n";
}
void Poly::SetDistanta()
{
int dx;
cout<<"Introduceti distanta dintre puncte: ";
cin>>dx;
this->dx = dx;
cout<<"\n";
}
void Poly::AfisareValori()
{
SetPolyn();
SetInterval();
SetDistanta();
int suma;
for(int i = a; i <= b; i+=dx){
suma = 0;
for(int j = 0; j <= grad; j++){
suma += coeficienti[j] * (pow (i,j));
}
cout<<"Valorea polinomului in punctul "<<i<<" este "<<suma<<"\n";
}
}
A polynomial P of degree ('grad' by your wording) N has N+1 coefficients;
In pseudo code:
length((N, N-1, ... 1, 0)) = N + 1.
thus this
void Poly::SetCoef()
{
/*...*/
this->coeficienti = new int[this->grad];
/*...*/
)
allocates one int too less.
Polynomials of even degree have an odd number N of coefficients, Polynomials of odd degree have an even number of coefficients.
I you allocate an int too less, the bucket too less for the polynomials of odd degree is at an boundary of a 2*sizeof(int) memory alignment; thus, it is likely that that bucket is not used otherwise.
This doesn't hold for even degrees, their missing bucket is within a new alignment block.
That's also the explanation for the discrepancy between debug and release mimics; the debug compiler run simply packs the memory less dense than the release compiler.
Besides that, you don't have to deal with manual field allocation at all for your purpose; e.g. std::vector and std::valarray automate that task in safe manner.

compare function for pairs not working

I have written my own compare function to sort a vector of pairs. My sort function should be like this.
The point (i,j) will be ahead of point(x,y) if it is closer to (5,5), vice-versa. I am finding the distance and then comparing based on that.
The code is
#include<iostream>
#include<stdlib.h>
#include<cstdio>
#include<vector>
#include<algorithm>
using namespace std;
double distance(int a, int b, int x, int y)
{
return sqrt(pow(a-x,2.0)+pow(b-y,2.0));
}
bool mycomp(const pair<int, int >&i, const pair<int, int >&j)
{
double dis=distance(i.first, i.second, 5,5);
double dis2=distance(j.first, j.second, 5, 5);
if(dis<dis2)
return i.first< j.first;
return i.first>j.first;
}
int main()
{
int n;
cin>>n;
vector<pair<int, int> > p;
for(int i=0; i < n; i++)
{
int a,b;
cin>>a >>b;
p.push_back(make_pair(a,b));
}
sort(p.begin(),p.end(),mycomp);
for(int i=0; i<n; i++)
cout<<p[i].first<<" "<<p[i].second<<endl;
return 0;
}
You did not specify what you mean by “not working,” so I’ll take that as license to point out anything I like about your code.
Your mycomp routine does not do what you describe. In particular, always make sure that a comparison routine is antisymmetric.
bool mycomp(const pair<int, int >&i, const pair<int, int >&j)
{
double dis=distance(i.first, i.second, 5, 5);
double dis2=distance(j.first, j.second, 5, 5);
if (dis < dis2) {
return true;
}
if (dis2 > dis) {
return false;
}
// tie break
return std::less<decltype(i)>(i,j);
}
If that line with the decltype does not work, you may have to spell the tie break out yourself.
The answer by #ChristopherCreutzig should solve your problem. I'm going to suggest something that will obviate the need for computing a square root.
int square(int a)
{
return a*a;
}
int distanceSquared(int a, int b, int x, int y)
{
return square(a-x) + square(b-y);
}
bool mycomp(const pair<int, int >&i, const pair<int, int >&j)
{
double dis1 = distanceSquared(i.first, i.second, 5, 5);
double dis2 = distanceSquared(j.first, j.second, 5, 5);
if ( dis1 != dis2 )
return (dis1 < dis2);
return (i.first < j.first);
}
This is not the right condition check.
if(dis<dis2)
return i.first< j.first
return i.first>j.first;
Should suffice return dis < dis2;

Finding an efficient algorithm to answer queries in a submatrix of a given square matrix

I'm trying to solving the “Rectangular Queries” problem from the December 2013 CodeChef contest:
Given a square matrix N x N, filled with integers from {1,..10}. We are given Q(10^5) queries as follows
given x1,y1, x2,y2 find the number of unique elements in the given sub matrix.
Limits:
N <= 300
Q (10^5)
x1 <= x2 <= N
y1 <= y2 <= N
time limit 1 sec.
I have tried an approach using std::set for uniqueness but getting TLE...MY approach is naive...looping from top left to bottom right for a query and adding elements to set..then printing std::set.size().
There are two possible approaches :-
Solve the problem on your own and get hard earned points.
Wait for contest to end and view solutions in editorials.
Good luck.
Here is a simple solution that would do it in time limit : -
#include<stdio.h>
#define max 300
int count[max][10][max];
int matrix[max][max];
int N;
void gen_counts() {
int i,j,k,number,index;
for(i=0;i<N;i++) {
for(j=0;j<10;j++)
count[i][j][0] = 0;
}
for(i=0;i<N;i++) {
for(j=0;j<10;j++) {
for(k=0;k<N;k++) {
if(k>0)
count[i][j][k] = count[i][j][k-1];
if(matrix[i][k]==j+1) {
count[i][j][k]++;
}
}
}
}
}
int get_distinct(int r1,int c1,int r2,int c2) {
int i,j,present[10],ret=0;
for(i=0;i<10;i++)
present[i] = 0;
for(i=r1;i<=r2;i++) {
for(j=0;j<10;j++) {
if(c1>0)
present[j]=present[j]||(count[i][j][c1-1]<count[i][j][c2]);
else present[j] = present[j] || (count[i][j][c1]>0||count[i][j][c2]>0);
}
}
for(i=0;i<10;i++)
ret = ret + present[i];
return(ret);
}
int main() {
int Q,i,j,r1,r2,c1,c2;
scanf("%d",&N);
for(i=0;i<N;i++) {
for(j=0;j<N;j++)
scanf("%d",&matrix[i][j]);
}
gen_counts();
scanf("%d",&Q);
for(i=0;i<Q;i++) {
scanf("%d%d%d%d",&r1,&c1,&r2,&c2);
printf("%d\n",get_distinct(r1-1,c1-1,r2-1,c2-1));
}
return(0);
}
i found the optimal algorithm for this problem ... i think its complexity is also less than O(n*n) . i think it will be useful
#include <stdio.h>
int main(void) {
int n,i,j;
//read matrix dimensions
scanf("%d",&n);
int mat[n][n];
int t,x1,x2,y1,y2;
int counter[10],flag;
//read matrix
for(i=0;i<n;i++){
for(j=0;j<n;j++){
scanf("%d",&mat[i][j]);
}
}
scanf("%d",&t);
//for each test case do this
while(t--){
scanf("%d%d%d%d",&x1,&y1,&x2,&y2);
//make all counters zero
for(i = 0;i<10;i++){
counter[i]=0;
}
flag = 0;
for(i=x1-1;i<=x2-1;i++){
for(j=y1-1;j<=y2-1;j++){
//counter == 0 means we are visiting the element for the first time
counter[mat[i][j]-1]++;
}
}
for(i =0;i<10 ;i++){
if(counter[i]!=0){
flag++;
}
}
printf("%d\n",flag);
}
return 0;
}

Graham scan c++ won't work

My code for the graham scan is not working, it is supposed to get the perimeter of the convex hull. It gets the input of n points, which can have decimals. The algorithm returns a value higher than the actual perimeter.
I am using what I understood from:
http://en.wikipedia.org/wiki/Graham_scan
#include <iostream>
#include <cstdio>
#include <cmath>
#include <vector>
#include <algorithm>
using namespace std;
#define PI 3.14159265
int nodes;
double xmin=10000000, ymin=10000000, totes=0;
struct ppoint
{
double x, y, angle;
void anglemake()
{
angle=atan2(y-ymin, x-xmin)*180/PI;
if(angle<0)
{
angle=360+angle;
}
}
} np;
The point structure, with a function to make the angle between it and the point with lowest y and x coordinates
vector<ppoint> ch, clist;
bool hp(ppoint i, ppoint j)
{
return i.angle<j.angle;
}
double cp(ppoint a, ppoint b, ppoint c)
{
return ((b.x-a.x)*(c.y-a.y))-((b.y-a.y)*(c.x-a.x));
}
The z-cross product function
double dist(ppoint i, ppoint j)
{double vd, hd;
vd=(i.y-j.y)*(i.y-j.y);
hd=(i.x-j.x)*(i.x-j.x);
return sqrt(vd+hd);
}
Distance generator
int main()
{
scanf("%d", &nodes);
for(int i=0; i<nodes; i++)
{
scanf("%lf%lf", &np.x, &np.y);
if(np.y<ymin || (np.y==ymin && np.x<xmin))
{
ymin=np.y;
xmin=np.x;
}
ch.push_back(np);
}
Gets the points
for(int i=0; i<nodes; i++)
{
ch[i].anglemake();
}
sort(ch.begin(), ch.end(), hp);
clist.push_back(ch[0]);
clist.push_back(ch[1]);
ch.push_back(ch[0]);
Sorts and starts Graham Scan
for(int i=2; i<=nodes; i++)
{
while(cp(clist[clist.size()-2], clist[clist.size()-1], ch[i])<0)
{
clist.pop_back();
}
clist.push_back(ch[i]);
}
Graham scan
for(int i=0; i<nodes; i++)
{
totes+=dist(clist[i], clist[i+1]);
}
Gets length of the perimeter
printf("%.2lf\n", totes);
return 0;
}
Just for the interest, print out value of nodes and clist.size() before the dist summming.
At glance clist can have nodes+1 items only if pop_back never happens. and if it does you have undefined behavior.
I think the problem is here:
for(int i=0; i<nodes; i++)
{
totes+=dist(clist[i], clist[i+1]);
}
clist will only have the remaining number of points, not nodes + 1 which is the number of points you loaded plus one. Storing this number in the first place is a fault IMHO, because it starts with the number of points, then you add one to close the loop, then again you remove points to make the hull convex. Just use container.size() and everything is clear.
One more note: Use a checked C++ standard library implementation for debugging. These would have warned you of undefined behaviour like accessing a vector beyond its range. C++ is a language that allows you to shoot yourself in the foot in to many ways, all in the name of performance. This is nice and well, unless when debugging, which is when you want the best diagnostics available.