模拟算法练习

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 }
View Code

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 }
View Code

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 }
View Code

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 }
View Code

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 }
View Code

7.2622 数字序列