模拟算法练习
Posted tech-chen
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了模拟算法练习相关的知识,希望对你有一定的参考价值。
codevs
1.1507 酒厂选址
1 #define N 10010 2 #include<iostream> 3 using namespace std; 4 #include<cstdio> 5 #include<cstring> 6 int sum[N],z[N],a[N]; 7 long long minn=-1; 8 int n; 9 int read() 10 { 11 int ans=0;char s; 12 s=getchar(); 13 while(s<\'0\'||s>\'9\') s=getchar(); 14 while(s>=\'0\'&&s<=\'9\') 15 { 16 ans=ans*10+s-\'0\'; 17 s=getchar(); 18 } 19 return ans; 20 } 21 void input() 22 { 23 n=read(); 24 for(int i=1;i<=n;++i) 25 { 26 z[i]=read(); 27 a[i]=read(); 28 29 } 30 sum[1]=0; 31 for(int i=2;i<=n;++i) 32 sum[i]=sum[i-1]+a[i-1]; 33 } 34 inline int min_count(int k,int i) 35 { 36 if(k>i) 37 { 38 return min((sum[k]-sum[i])*z[i],(sum[n]-sum[k]+sum[i]+a[n])*z[i]); 39 } 40 else 41 { 42 return min((sum[i]-sum[k])*z[i],(a[n]+sum[n]-sum[i]+sum[k])*z[i]); 43 } 44 } 45 void chuli(int k) 46 { 47 long long ans=0; 48 for(int i=1;i<=n;++i) 49 { 50 if(i==k) continue; 51 ans+=min_count(k,i); 52 } 53 if(minn<0) 54 minn=ans; 55 else minn=min(ans,minn); 56 } 57 int main() 58 { 59 input(); 60 for(int i=1;i<=n;++i) 61 chuli(i); 62 cout<<minn<<endl; 63 return 0; 64 }
2.2621 土地侵蚀
1 #define pi 3.141592654 2 #include<iostream> 3 using namespace std; 4 #include<cstdio> 5 #include<cmath> 6 double x,y,temp=50,sum=0; 7 int year=0; 8 int main() 9 { 10 cin>>x>>y; 11 if(x<0||y<0) 12 { 13 cout<<0<<endl; 14 return 0; 15 } 16 while(true) 17 { 18 double r=2*sum/pi; 19 if(x*x+y*y<r) 20 { 21 printf("%d\\n",year); 22 break; 23 } 24 year++; 25 sum+=50; 26 } 27 return 0; 28 }
3.3016 质子撞击炮 II
1 #define N 1050 2 #include<cstdio> 3 #include<cstring> 4 #include<iostream> 5 using namespace std; 6 int jz[N][N]; 7 int n; 8 int xx[9]={0,0,0,1,1,1,-1,-1,-1}; 9 int yy[9]={0,1,-1,0,1,-1,0,1,-1}; 10 int read() 11 { 12 int ans=0; 13 char s; 14 while(s<\'0\'||s>\'9\') s=getchar(); 15 while(\'0\'<=s&&s<=\'9\') 16 { 17 ans=ans*10+s-\'0\'; 18 s=getchar(); 19 } 20 return ans; 21 } 22 int main() 23 { 24 memset(jz,127,sizeof(jz)); 25 int sum=0; 26 n=read(); 27 for(int i=1;i<=n;++i) 28 for(int j=1;j<=n;++j) 29 { 30 jz[i][j]=read(); 31 if(jz[i][j]==0) jz[i][j]=N; 32 } 33 for(int i=1;i<=5;++i) 34 { 35 int x,y; 36 x=read();y=read(); 37 jz[x][y]--; 38 for(int j=0;j<9;++j) 39 { 40 int x1=x+xx[j],y1=y+yy[j]; 41 jz[x1][y1]--; 42 if(jz[x1][y1]<=0) 43 { 44 sum++; 45 jz[x1][y1]=N; 46 } 47 } 48 } 49 cout<<sum<<endl; 50 return 0; 51 }
4.2927 集合(膜拜FTC大神(虽然我也不知道是谁))
时间限制: 2 s
空间限制: 128000 KB
题目等级 : 钻石 Diamond
题目描述 Description
给出n个集合,每个集合中有若干个数。
有m个询问,每次询问两个数a,b,判断a、b是否同时存在于某一个集合中。
输入描述 Input Description
第一行为n。
接下来的n行,每行描述一个集合,每行的第一个数为该集合中数的个数k,接下来有k个数。数字可能有重复。
第n+2行为m。
接下来的m行,每行两个数a、b,表示一个询问。
输出描述 Output Description
对于每次询问,输出一行。若a、b同时存在于某一个集合中,输出Y,否则输出N。
样例输入 Sample Input
3
2 1 2
3 2 3 4
3 2 5 7
2
1 3
2 7
样例输出 Sample Output
N
Y
数据范围及提示 Data Size & Hint
n<=1000,k<=10000,m<=2000000,集合中的数字小于10000,a、b<=32767,不保证a!=b。不保证任意两个集合不同。集合中的数与询问的数均为非负整数。
1 /*我一开始用set爆了空间,用Hash又超时了,还是FTC大神的代码牛B*/ 2 /*----------------超时代码---------------------------------*/ 3 #include<cstdio> 4 #include<iostream> 5 #define N 1001 6 #include<cstring> 7 #define mod 10007 8 using namespace std; 9 int n,k,m,a,b; 10 struct Hash{ 11 int s[mod]; 12 Hash(){memset(s,-1,sizeof(s));} 13 void insert(int x) 14 { 15 int k=x%mod; 16 while(s[k]!=x&&s[k]!=-1) 17 { 18 k++; 19 k%=mod; 20 } 21 s[k]=x; 22 } 23 bool count(int x) 24 { 25 int k=x%mod; 26 int t=0; 27 while(s[k]!=x) 28 { 29 k++; 30 k%=mod; 31 t++; 32 if(t>mod) break; 33 } 34 if(t>mod) return false; 35 return true; 36 } 37 }se[N]; 38 int read() 39 { 40 int ans=0;char s; 41 s=getchar(); 42 while(s<\'0\'||s>\'9\') s=getchar(); 43 while(\'0\'<=s&&s<=\'9\') 44 ans=ans*10+s-\'0\',s=getchar(); 45 return ans; 46 } 47 int main() 48 { 49 n=read(); 50 for(int i=1;i<=n;++i) 51 { 52 k=read(); 53 while(k--) 54 { 55 int a; 56 a=read(); 57 se[i].insert(a); 58 } 59 } 60 m=read(); 61 while(m--) 62 { 63 a=read();b=read(); 64 if(a>10000||b>10000) 65 { 66 printf("N\\n"); 67 continue; 68 } 69 for(int i=1;i<=n;++i) 70 { 71 if(se[i].count(a)&&se[i].count(b)) 72 { 73 printf("Y\\n"); 74 break; 75 } 76 if(i==n) 77 printf("N\\n"); 78 } 79 } 80 return 0; 81 } 82 /*----------------------正确代码以及神一般的思路------------------------*/ 83 /*这种方法对于数的范围较小但是集合数目很多,数的量很大,的题目,很实用的*/ 84 #include<iostream> 85 using namespace std; 86 #include<cstdio> 87 #define N 10002 88 unsigned long long topt[N][20]={0};/*1000/64==15*/ 89 int n,m,k,a,b; 90 int read() 91 { 92 int ans=0;char s; 93 s=getchar(); 94 while(s<\'0\'||s>\'9\') s=getchar(); 95 while(\'0\'<=s&&s<=\'9\') 96 { 97 ans=ans*10+s-\'0\'; 98 s=getchar(); 99 } 100 return ans; 101 } 102 inline void insert(int i,int x) 103 { 104 topt[x][i/64]|=(1ull<<(i%64)); 105 /*第一维表示的是原数,还要有一个1000位的二进制表示存在于哪个集合当中,因为1000位太多了,无论是第二维还是数组的值都是存不开的,就平分,第二维储存着1000位数分成了几分,集合的数储存着这一份中的这些集合有没有这个数,所以要i/64,i%64,使用无符号长整形ull后缀1,可以解决符号位的影响*/ 106 } 107 int main() 108 { 109 n=read(); 110 for(int i=1;i<=n;++i) 111 { 112 k=read(); 113 for(int j=1;j<=k;++j) 114 { 115 a=read(); 116 insert(i,a); 117 } 118 } 119 m=read(); 120 while(m--) 121 { 122 a=read();b=read(); 123 if(a>10000||b>10000) 124 { 125 printf("N\\n"); 126 continue; 127 } 128 for(int i=0;i<=16;i++) 129 {/*查询时,直接把每一份位运算,只要不是0,就说明在同一个集合,多么神奇的做法*/ 130 if(topt[a][i]&topt[b][i]) 131 { 132 printf("Y\\n");break; 133 } 134 if(i==16) 135 { 136 printf("N\\n"); 137 } 138 } 139 } 140 return 0; 141 }
5.1445 送Q币
1 #include<iostream> 2 #define N 15 3 #include<cstdio> 4 #include<cstring> 5 using namespace std; 6 int sum[N]={0}; 7 #include<map> 8 map<string,int>ma; 9 int ksum[N]; 10 string s[N]; 11 int n,topt; 12 int main() 13 { 14 scanf("%d",&n); 15 for(int i=1;i<=n;++i) 16 { 17 cin>>s[i]; 18 ma[s[i]]=i; 19 sum[i]=0; 20 } 21 string ss; 22 while(cin>>ss) 23 { 24 int k=ma[ss]; 25 int num,numk; 26 scanf("%d",&num); 27 ksum[k]=num; 28 sum[k]+=num; 29 string nam; 30 scanf("%d",&numk); 31 if(numk==0) continue; 32 int mony=num/numk; 33 sum[k]=sum[k]-mony*numk; 34 while(numk--) 35 { 36 cin>>nam; 37 int t=ma[nam]; 38 sum[t]+=mony; 39 } 40 } 41 for(int i=1;i<=n;++i) 42 { 43 cout<<s[i]<<" "<<sum[ma[s[i]]]-ksum[ma[s[i]]]<<endl; 44 } 45 return 0; 46 }
6.1054 电梯
1 #include<iostream> 2 using namespace std; 3 #include<cstdio> 4 long long tim=0; 5 int n; 6 int now=0,k; 7 int main() 8 { 9 scanf("%d",&n); 10 while(n--) 11 { 12 scanf("%d",&k); 13 if(k>=now) 14 { 15 tim+=(k-now)*6+5; 16 } 17 else { 18 tim+=(now-k)*4+5; 19 } 20 now=k; 21 } 22 cout<<tim<<endl; 23 return 0; 24 }
7.2622 数字序列