2) 可以将三个点作为一组p1(x1,y1),p2(x2,y2),p3(x3,y3),判断Kp1p2是否等于Kp2p3只需要判断(y2-y1)*(x2-x1)是否等于(y3-y2)*(x2-x1),此时就不用判断斜率了,但是要注意两个点的时候要特判!(上述等式是两个斜率对角相乘)
//用三个点的方法判断
#include <iostream> #include <cstdio> #include <cmath> #include <algorithm> #include <cstring> using namespace std; #define N 1000005 int x[N],y[N]; int main() { int n,m,flag; while(~scanf("%d",&n)) { flag = 0; for(int i=0; i<n; i++) scanf("%d%d",&x[i],&y[i]); if(n>2) { for(int i=2; i<n; i++) { if((y[i]-y[i-1])*(x[i-1]-x[i-2])!=(x[i]-x[i-1])*(y[i-1]-y[i-2])) { flag =1; break; } } } if(!flag||n==2) printf("YES\n"); else printf("NO\n"); } return 0; }
//两个点判断
#include<bits/stdc++.h> using namespace std; typedef long long ll; int main() { int n; double x, y, a, b, ans; while(~scanf("%d", &n)) { scanf("%lf%lf", &x,&y); scanf("%lf%lf", &a,&b); int flag = 0; if(a == x) flag = 1; else ans = fabs(b-y)/fabs(a-x); for(int i=3; i<=n; i++) { scanf("%lf%lf", &a,&b); if(flag == 1) { if(a != x) flag = 2; } else if(fabs((b-y)/(a-x) - (ans)) > 1e-5) flag = 2; } if(flag > 1) puts("NO"); else puts("YES"); } return 0; }
题目链接:http://oj.jxust.cn/problem.php?id=1276
greedy:
要使花费时间最短,就应该使做题的顺序中有更多的后面的题目长度和难度系数大于等于前面的长度和难度系数的片段, 所以可以先按照长度由小到大排序,如果长度相等则按难度系数从小到大排序。然后再按顺序找出长度和难度系数也比前面一个大或等于的题目,看最多有多少个连续的片段, n-连续片段的数量就是answer. 复杂度为O(n*n).
#include <iostream> #include <cstdio> #include <cmath> #include <algorithm> #include <cstring> using namespace std; #define N 5005 int vis[N]; struct node { int time; int level; }; int cmp(node a,node b) { if(a.time==b.time) return a.level<b.level; else return a.time<b.time; } node ans[N]; int main() { int T,n,sum,res; cin>>T; while(T--) { sum = 0; cin>>n; memset(vis,0,sizeof(vis)); for(int i=0; i<n; i++) cin>>ans[i].time>>ans[i].level; sort(ans,ans+n,cmp); for(int i=0; i<n; i++) { if(!vis[i]) { res = i; //cout<<ans[i].level; for(int j=i+1; j<n; j++) { if(ans[res].level<=ans[j].level&&!vis[j]) { vis[j] = 1; res = j; // cout<<" "<<ans[j].level; } } //cout<<endl; sum++; } } cout<<sum<<endl; } return 0; }
1277:吃货问生日
http://oj.jxust.cn/problem.php?cid=1046&pid=2
其实就是一道升级版的判断闰年
//普通版 //by:qwn3213 //从开始年到结束年,遍历一遍,判断每一年是否是闰年,时间复杂度为O(n)。 #include <iostream> #include <cstdio> #include <cstring> #include <algorithm> using namespace std; bool isLeap(int y) { if(y%400==0||y%4==0&&y%100!=0) return true; else return false; } int main() { char month[][20]= {"sb","January","February","March","April","May","June","July","August","September","October","November" ,"December"}; int t,j,i,year1,year2,day1,day2,month1,month2,ans; char m1[20],m2[20]; cin>>t; for(i=1; i<=t; i++) { ans=0; scanf("%s %d,%d",&m1,&day1,&year1); scanf("%s %d,%d",&m2,&day2,&year2); for(j=1; j<13; j++) if(strcmp(m1,month[j])==0) { month1=j; break; } for(j=1; j<13; j++) if(strcmp(m2,month[j])==0) { month2=j; break; } if(year1==year2) { if(isLeap(year1)) if((month1<3&&month2>2)||(month2==2&&day2==29)) ans=1; } else { for(j=year1+1;j<year2;j++) if(isLeap(j)) ans++; if(isLeap(year1)) if(month1<3) ans++; if(isLeap(year2)) if(month2>2||(month2==2&&day2==29)) ans++; } printf("Case #%d: %d\n",i,ans); } return 0; } //高级版 //by:qwn3213 //时间复杂度为O(1),这道题其实一开始我year的范围是设定到10亿的,这样O(n)方法就超时了 //后来降低难度了,没想到还是只有两个人AC了 #include <iostream> #include <cstdio> #include <cstring> #include <algorithm> using namespace std; int main() { int t,j,i,year1,year2,day1,day2,ans,monthth1,month2; char m1[20],m2[20]; int a,b; cin>>t; for(i=1; i<=t; i++) { ans=0; scanf("%s %d,%d",&m1,&day1,&year1); scanf("%s %d,%d",&m2,&day2,&year2); if(strcmp(m1,"January")==0||(strcmp(m1,"February")==0&&day1<=29)) year1--; if(strcmp(m2,"January")==0||(strcmp(m2,"February")==0&&day2<29)) year2--; a=year2/4-year2/100+year2/400; //a:year2是第几个闰年 b=year1/4-year1/100+year1/400; ans+=a-b; printf("Case #%d: %d\n",i,ans); } return 0; }
1278:Operate Sequence
http://oj.jxust.cn/problem.php?id=1278
只是想写个英文标题吓吓大家,结果比赛的时候真没人做。。
其实这题很简单:要把最后一个元素一个一个放到最前面去使得其变成一个非递减序列就必须满足两个条件:①原先的序列原本就是非递减的,或者它有两段非递减序列(想想看是不是)。②原先序列的最后一个元素要比第一个元素小或相等(要不然放到前面去也不会是非递减的)。满足这两个限制条件就可以操作成非递减序列了,求最小操作数就是找出原先序列中最先不符合非递减序列的数的位置,你说把那个数放到序列中第一个位置最少需要几步?如果原本就是非递减的答案就是0.
#include <iostream> #include <cstdio> #include <cmath> #include <algorithm> #include <cstring> using namespace std; #define N 100005 int res[N]; int main() { int T,n,ans,i,j,k,flag; cin>>T; while(T--) { flag = 0; scanf("%d",&n); for(i=0; i<n; i++) scanf("%d",&res[i]); for(i=1; i<n; i++) if(res[i]<res[i-1]) break; for(j=i+1;j<n;j++) { if(res[j]<res[j-1]) { flag = 1; break; } } if((!flag&&res[n-1]<=res[0])||(!flag&&i==n)) cout<<n-i<<endl; else cout<<-1<<endl; } return 0; }
1279:出题,一开始我是拒绝的
题目链接:http://oj.jxust.cn/problem.php?cid=1046&pid=4
数组A、B数据量都是10000,所以这道题不能开数组存C,再排序,再遍历
#include <iostream> #include <cstdio> #include <cstring> #include <algorithm> using namespace std; //by:qwn3213 int main() { int a[10240],b[10240],n,m,k,i,j,ans; while(cin>>n>>m>>k) { ans=1; for(i=0;i<n;i++) scanf("%d",&a[i]); for(j=0;j<m;j++) scanf("%d",&b[j]); sort(a,a+n); sort(b,b+m); j=m-1; for(i=0;i<n;i++) { for(;j>=0&&a[i]+b[j]>=k;j--); //因为a、b都有序的所以j每次不需要从头到尾遍历, //可以从上次的结果开始,减少很多很多时间 //其实这也可以用二分做,自己想去吧 ans+=j+1; } cout<<ans<<endl; } }
1281:加油吧,兄弟!
http://oj.jxust.cn/problem.php?id=1281
这道题有点贪心的感觉,找到一种最优解。这道题目还是挺有趣的,很多人赛后问我说这道题我尽量将1,11,111……加入其中怎么就错了,然后我给了他一个20的数据,他就回了句。。。。,这道题的要求是输出个数最少的完美数,咋一看还是挺难的,仔细一看也还是不简单哈,其实解法很简单,就是要自己仔细分析,找出他们之间的一种规律(这就要靠大家自己平时做题的积累了)。这题只需要先判断几位数然后将每一位数字跟1比较,若大于等于1,则赋1,否则赋0.
例如: 2054 先将2跟1比较,2>1,故第一位赋1,第二位0,0<1,故第二位赋0,第三位5>1,故第三位赋1,第四位4,4>1,故赋1.
所以第一个数就是:1011,剩下2054 - 1011 = 1043,然后按照这种方式继续下去。
#include <iostream> #include <algorithm> #include <cmath> using namespace std; int main() { int a[100]; int T,n,flag,i,j,k,t,ans[100],res[100],temp,MAX,sum; cin>>T; while(T--) { cin>>n; k=0; temp = n; while(temp) { ans[k] = temp%10; a[k++]=temp%10; temp = temp/10; } sort(a,a+k); MAX = a[k-1]; cout<<MAX<<endl; for(i=0;i<MAX;i++) { flag = 0,sum=0,t=0; for(j=0;j<k;j++) { if(ans[j]>=1) { res[flag++] = 1; ans[j]--; } else res[flag++] = 0; } for(j=0;j<flag;j++) sum+=(res[j]*pow(10.0,t++)); if(i==0) cout<<sum; else cout<<" "<<sum; } cout<<endl; } return 0; }