Contest 7.21(贪心专练)
这一次都主要是贪心练习
练习地址http://acm.hust.edu.cn/vjudge/contest/view.action?cid=26733#overview
Problem APOJ 1328
对于每一个点,可以找到他在x轴上的可行区域,这样的话就变为了对区间的贪心。
1 #include<iostream>
2 #include<stdio.h>
3 #include<string.h>
4 #include<map>
5 #include<vector>
6 #include<set>
7 #include<stack>
8 #include<queue>
9 #include<algorithm>
10 #include<cmath>
11 #include<stdlib.h>
12 using namespace std;
13 #define MAX(a,b) (a > b ? a : b)
14 #define MIN(a,b) (a < b ? a : b)
15 #define MAXN 10000001
16 #define INF 1000000007
17 #define mem(a) memset(a,0,sizeof(a))
18 #define eps 1e-15
19
20 struct node{double s,t;}ma[1001];
21 double R;
22 int N;
23
24
25 const int island_max=1000;
26
27
28 void get_len(int index,double a,double b)
29 {
30 double temp = sqrt(R*R - b*b);
31 ma[index].s=a-temp;
32 ma[index].t=a+temp;
33 }
34
35 int cmp(node a,node b)
36 {
37 if(a.t!=b.t)return (a.t < b.t);
38 return (b.s > a.s);
39 }
40
41 int main()
42 {
43 int ca = 1;
44 while(~scanf("%d%lf",&N,&R) && (N || R))
45 {
46 int i;
47 double a,b;
48 int flag = 0;
49 for(i=0;i<N;i++)
50 {
51 scanf("%lf %lf",&a,&b);
52 if(b<=R && !flag)
53 {
54 get_len(i,a,b);
55 }
56 else flag = 1;
57 }
58 if(flag){printf("Case %d: -1\n",ca++);continue;}
59 sort(ma,ma+N,cmp);
60 double key = ma[0].t;
61 int ans=1;
62 for(i=1;i<N;i++)
63 {
64 if(ma[i].s-key >eps)
65 {
66 key = ma[i].t;
67 ans ++;
68 }
69 }
70 printf("Case %d: %d\n",ca++,ans);
71 }
72 return 0;
73 }
Problem B POJ 2109
可以拿double水过pow(p,1/n)
1 //Memory Time
2 //280K 0MS
3
4 #include<iostream>
5 #include<math.h>
6 using namespace std;
7
8
9 int main(void)
10 {
11 double n,p;
12 while(cin>>n>>p)
13 cout<<pow(p,1.0/n)<<endl; //指数的倒数就是开n次方
14 return 0;
15 }
另外,看大神的二分+大数乘法
http://paste.ubuntu.com/5906043/
然后我也写了一个(在章爷的指导下终于AC了)
1 #include <stdio.h> 2 #include <math.h> 3 #include <string.h> 4 #define MAX(a,b) (a)>(b)?(a):(b) 5 6 7 void strrevv(char s[]) 8 { 9 int i=0,j=strlen(s)-1; 10 while(i<j) 11 { 12 int a = s[i]; 13 s[i] = s[j]; 14 s[j] = a; 15 i++;j--; 16 } 17 } 18 19 char ans[205]; 20 char* huge_multiply(char s[],char t[]) 21 { 22 int a[205]; 23 memset(a, 0, sizeof(a)); 24 memset(ans,0,sizeof(ans)); 25 strrevv(s);strrevv(t); 26 int lens = strlen(s), lent = strlen(t),i,j; 27 for(i=0;i<lens;i++) 28 { 29 for(j=0;j<lent;j++) 30 { 31 a[i+j] += (s[i] - '0')*(t[j] - '0'); 32 } 33 } 34 i=200; 35 while(a[i] == 0) 36 i--; 37 for(j=0;a[j] || j<=i;j++) 38 { 39 a[j+1]+=a[j]/10; 40 a[j] = a[j]%10; 41 } 42 for(i=0;i<j;i++) 43 { 44 ans[i]=a[i]+'0'; 45 } 46 strrevv(ans); 47 strrevv(s);strrevv(t); 48 return ans; 49 } 50 51 char res[205]={0}; 52 char re[205]={0}; 53 char* power(char p[],int n) 54 { 55 if(n == 1)return p; 56 char* pstr; 57 pstr = power(p,n/2); 58 strcpy(re,pstr); 59 strcpy(res,pstr); 60 pstr = huge_multiply(re, res); 61 strcpy(re,pstr); 62 if(n%2)pstr = huge_multiply(re, p); 63 strcpy(re, pstr); 64 return re; 65 } 66 67 //30517578125000 68 69 70 71 int compare_str(char *s, char *t) 72 { 73 int lens = strlen(s); 74 int lent = strlen(t); 75 if(lens != lent)return lens < lent ? -1 : 1; 76 while(*s == *t && *s){s++;t++;} 77 if(!(*s))return 0; 78 return *s < *t ? -1: 1; 79 } 80 81 int b_search(int n, char* p) 82 { 83 char str[12]={0}; 84 char *pstr; 85 int l = 0,r = 1000000002; 86 int lenp = strlen(p); 87 int ans = 1,compare; 88 while(r - l > 1) 89 { 90 ans = (l+r)/2; 91 sprintf(str,"%d", ans); 92 int lenstr = strlen(str)-1; 93 if(lenstr*n > lenp){r=ans;continue;} 94 pstr = power(str, n); 95 compare = compare_str(pstr, p); 96 if(compare == 0)break; 97 else if(compare < 0)l = ans; 98 else r = ans; 99 // printf("%d %d %d\n",l,r,ans); 100 } 101 if(l == r)return ans - 1; 102 return ans; 103 } 104 105 106 int main() 107 { 108 int n; 109 char pstr[110]={0}; 110 while(~scanf("%d %s", &n, pstr)) 111 { 112 char *p = pstr; 113 printf("%d\n", b_search(n, p)); 114 } 115 return 0; 116 }
Problem CPOJ 2586
由于每个月的亏损或是盈利是固定的,所以我们按贪心的思想,为了让亏损的影响到更多的月份,我们让亏损的尽量放在后面,又由于亏损金额是不会变化的,所以可以分类处理盈利s,亏损d
如果五个月内只有x个月是亏损的 盈利
x = 1 ssssd,ssssd,ss如果是这样的话,只需要d>4s 10s-2d
x = 2 sssdd,sssdd,ss 2*d>3*s 8s-4d
x = 3 ssddd,ssddd,ss 3*d>2*s 6s-6d
x = 4 sdddd,sdddd,sd 4*d>s 3s-9d
x = 5 一定亏损
当然也可以枚举过(一共也就2^12中情况)
1 #include<stdio.h> 2 #include<stdlib.h> 3 4 int main() 5 { 6 int s, d, re; 7 while(scanf("%d%d",&s, &d)==2) 8 { 9 if(4*s-d<0) 10 re=10*s-2*d; 11 else if(3*s-2*d<0) 12 re=8*s-4*d; 13 else if(2*s-3*d<0) 14 re=6*s-6*d; 15 else if(s-4*d<0) 16 re=3*s-9*d; 17 else 18 re=-1; 19 if(re<0) 20 printf("Deficit\n"); 21 else 22 printf("%d\n", re); 23 } 24 return 0; 25 }
Problem D URAL 1303
感觉自己没有错了,还是WA,不做了
ural 1303 Minimal Coverage(贪心)
Problem E SGU 195
题木意思就是说第i+1个的上司是num[i],而一个人要么给下属发钱,要么从上司拿钱,问这个图里面最多可以拿到多少钱。
由于num[i]是下属是i+1所以可以从后往前扫一遍(也就是从叶子往根找),同时标记一下就可以了
1 #include<iostream> 2 #include<stdio.h> 3 #include<string.h> 4 #include<map> 5 #include<vector> 6 #include<set> 7 #include<stack> 8 #include<queue> 9 #include<algorithm> 10 #include<cmath> 11 #include<stdlib.h> 12 using namespace std; 13 #define MAX(a,b) (a > b ? a : b) 14 #define MIN(a,b) (a < b ? a : b) 15 #define MAXN 500005 16 #define INF 1000000007 17 #define mem(a) memset(a,0,sizeof(a)) 18 #define eps 1e-15 19 20 int vis[MAXN], p[MAXN], ans[MAXN]; 21 int N; 22 23 24 int main() 25 { 26 mem(vis); 27 scanf("%d",&N); 28 int i,a; 29 for(i=2;i<=N;i++) 30 { 31 scanf("%d",&a); 32 p[i]=a; 33 } 34 int num=0; 35 for(i=N;i>=2;i--) 36 { 37 if(!vis[i] && !vis[p[i]]) 38 { 39 vis[p[i]] = vis[i] = 1; 40 ans[num++] = i; 41 } 42 } 43 printf("%d\n",num*1000); 44 sort(ans,ans+num); 45 for(i=0;i<num;i++) 46 { 47 printf("%d%c", ans[i],i==num-1?'\n':' '); 48 } 49 return 0; 50 }
Problem F SGU 171
不是很好做,是很不好做。题解见http://www.cnblogs.com/gj-Acit/p/3213370.html