首页 > 代码库 > hiho_offer收割18_题解报告_差第四题

hiho_offer收割18_题解报告_差第四题

I.求逆元
欧几里得方法

II.模拟
细心+耐心

*本人感悟:
自己的错误在于:
对于这道模拟题没有耐心静下来一字一字看题,一行一行调错,一步一步调试,我要引以为戒。


III.dp
f[i][j][k]=max(f[i-1][j][k],min(f[i-1][t][k-1])+value[i][k])
t=0,1,…,801

i为第i个曲子(长度为3)
j为至今已进行j次的和弦改变(j<=c(c为允许和弦改变的最多次数))
k为第k种和弦的方法
value[i][k]为用对第i个曲子用第k个和弦的不和谐值

本人想到的进一步优化(本题不用):
1.求出全程不能变音的最小值

2.对于某个变音方法,如果其值已经大于最小值,则该方法不能继续进行下去

具体操作:
把对应第1~i个曲子可以实现的和弦存放到数组,生成第1~i+1个曲子可以实现的和弦

时间复杂度:
i<=1000
j<=20
k<=802

对于每个i,k,求出一次min(f[i-1][t][k-1])即可

O(nk*802)
1000*20*802=16040000
可在一秒内解决

*另:注意数组维数的范围
如发现错误,可在各个位置设置“输出一个数”,看哪里不正常,那么就是哪里出错了

*测试数据:
如n=1000,k=20
其它全为0
判断是否数组开的正确

IV.
实际上,没多少斤两就不要想第四题了,看看题目和测试数据就知道是不想让你用简单方法拿点分了

 

反正不会做
下面是想法:


不同的分图没有边相连,不互相影响,可分开考虑

以k个点为标准点,分别考虑这k个点是否发生故障,除去??? 不行,2^k 太大了

 

有第i个点和有第j点,

 


当某边在/不在时

当某点在/不在时

 


当n很大时

当m很大时

 

极限数据:
100000个点,编号为前400的点,每个点之间都有一个边相连;剩下的点都仅与编号为1的点相连

 

 1.

 1 #include <stdio.h>
 2 #include <stdlib.h>
 3 
 4 long s,t;
 5 
 6 void gcd(long x,long y)
 7 {
 8     if (y==0)
 9     {
10         s=1;
11         t=0;
12         return;
13     }
14     long r,q;
15     r=x/y;
16     gcd(y,x%y);
17     q=s;
18     s=t;
19     t=q-r*t;
20 }
21 
22 int main()
23 {
24     long a,b,p;
25     scanf("%ld%ld%ld",&a,&b,&p);
26     b=b%p;
27     gcd(p,b);
28     t=t%p+p;
29     printf("%ld\n",a*t%p);
30     return 0;
31 }

 

2.

  1 #include <stdio.h>
  2 #include <stdlib.h>
  3 #include <stdbool.h>
  4 #include <string.h>
  5 
  6 struct node
  7 {
  8     long f[4];
  9     long a[3];
 10 }pai[10];
 11 
 12 long n;
 13 
 14 bool judge()
 15 {
 16     long j,k,g;
 17     //1
 18     for (j=0;j<4;j++)
 19     {
 20         g=0;
 21         for (k=0;k<n;k++)
 22             g+=pai[k].f[j];
 23         if (g==5)
 24             return true;
 25     }
 26     //2
 27     for (j=0;j<n;j++)
 28         if (pai[j].a[0]>0)
 29             break;
 30     if (j!=n)
 31     {
 32         for (j=0;j<n;j++)
 33             if (pai[j].f[0]+pai[j].f[1]+pai[j].f[2]+pai[j].f[3]>0)
 34                 break;
 35         if (j!=n)
 36         {
 37             for (j=0;j<n;j++)
 38                 if (pai[j].f[3]>0)
 39                     break;
 40             if (j==n)
 41                 return true;
 42         }
 43     }
 44     //3
 45     for (j=0;j<n;j++)
 46         if (pai[j].a[1]>0)
 47             break;
 48     if (j!=n)
 49     {
 50         for (j=0;j<n;j++)
 51             if (pai[j].f[0]+pai[j].f[1]+pai[j].f[2]+pai[j].f[3]>0)
 52                 break;
 53         if (j!=n)
 54         {
 55             for (j=0;j<n;j++)
 56                 if (pai[j].f[1]>0)
 57                     break;
 58             if (j==n)
 59                 return true;
 60         }
 61     }
 62     //4
 63     for (j=0;j<n;j++)
 64         if (pai[j].a[2]>0)
 65             break;
 66     if (j!=n)
 67     {
 68         for (j=0;j<n;j++)
 69             if (pai[j].f[0]+pai[j].f[1]+pai[j].f[2]+pai[j].f[3]>0)
 70                 break;
 71         if (j!=n)
 72             return true;
 73     }
 74     return false;
 75 }
 76 
 77 int main()
 78 {
 79     long c,g,t,i,j,k,sum[10],tot[10],num;
 80     char s[50];
 81     scanf("%ld%ld",&n,&c);
 82     for (i=0;i<n;i++)
 83         sum[i]=10000000;
 84     for (i=0;i<n;i++)
 85         tot[i]=0;
 86     num=0;
 87     for (i=1;i<=c;i++)
 88     {
 89         scanf("%s",s);
 90         if (strcmp(s,"Fruit")==0)
 91         {
 92             tot[num]++;
 93             sum[num]--;
 94             for (j=0;j<4;j++)
 95                 pai[num].f[j]=0;
 96             for (j=0;j<3;j++)
 97                 pai[num].a[j]=0;
 98             scanf("%ld",&g);
 99             for (j=1;j<=g;j++)
100             {
101                 scanf("%ld",&t);
102                 pai[num].f[t]++;
103             }
104             num=(num+1)%n;
105         }
106         else if (strcmp(s,"Animal")==0)
107         {
108             tot[num]++;
109             sum[num]--;
110             for (j=0;j<4;j++)
111                 pai[num].f[j]=0;
112             for (j=0;j<3;j++)
113                 pai[num].a[j]=0;
114             scanf("%ld",&t);
115             pai[num].a[t]=1;
116             num=(num+1)%n;
117         }
118         else
119         {
120             scanf("%ld",&t);
121             if (judge()==true)
122             {
123                 for (j=0;j<n;j++)
124                     sum[t]+=tot[j];
125                 for (j=0;j<n;j++)
126                 {
127                     tot[j]=0;
128                     for (k=0;k<4;k++)
129                         pai[j].f[k]=0;
130                     for (k=0;k<3;k++)
131                         pai[j].a[k]=0;
132                 }
133             }
134             else
135             {
136                 sum[t]-=n;
137                 for (j=0;j<n;j++)
138                     sum[j]++;
139             }
140             num=t;
141         }
142         //printf("%ld %ld %ld\n",sum[0],sum[1],sum[2]);
143     }
144     for (i=0;i<n;i++)
145         printf("%ld\n",sum[i]);
146     return 0;
147 }

 

3.

 1 #include <stdio.h>
 2 #include <stdlib.h>
 3 #include <math.h>
 4 #define maxf 10000000
 5 //max=400*3000=1200000
 6 
 7 long music[3001],value[1001][802],f[1001][21][802],ch[1001];
 8 
 9 long min(long a,long b)
10 {
11     if (a>b)
12         return b;
13     else
14         return a;
15 }
16 
17 int main()
18 {
19     long n,g,i,j,k,l,m,pr;
20     scanf("%ld%ld",&n,&g);
21     for (i=1;i<=3*n;i++)
22         scanf("%ld",&music[i]);
23     for (i=0;i<=400;i++)
24     {
25         j=i-200;
26         l=0;
27         m=0;
28         for (k=1;k<=n;k++)
29         {
30             m++;
31             value[m][i]=0;
32             l++;
33             value[m][i]+=abs(j-music[l]);
34             l++;
35             value[m][i]+=abs(j+4-music[l]);
36             l++;
37             value[m][i]+=abs(j+7-music[l]);
38         }
39     }
40 
41     for (i=401;i<=801;i++)
42     {
43         j=i-601;
44         l=0;
45         m=0;
46         for (k=1;k<=n;k++)
47         {
48             m++;
49             value[m][i]=0;
50             l++;
51             value[m][i]+=abs(j-music[l]);
52             l++;
53             value[m][i]+=abs(j+3-music[l]);
54             l++;
55             value[m][i]+=abs(j+7-music[l]);
56         }
57     }
58 
59     for (i=1;i<=n;i++)
60         for (j=1;j<=g;j++)
61             for (k=0;k<802;k++)
62                 f[i][j][k]=maxf;
63 
64     for (k=0;k<802;k++)
65         f[0][0][k]=0;
66     for (i=1;i<=n;i++)
67         for (k=0;k<802;k++)
68             f[i][0][k]=f[i-1][0][k]+value[i][k];
69 
70     pr=maxf;
71     //2
72     for (i=2;i<=n;i++)
73     {
74         //0 <g
75         for (j=0;j<min(i-1,g);j++)
76         {
77             ch[j]=maxf;
78             for (k=0;k<802;k++)
79                 ch[j]=min(ch[j],f[i-1][j][k]);
80         }
81         //1(0 不用计算)
82         for (j=0;j<=min(i-1,g);j++)
83         {
84             for (k=0;k<802;k++)
85             {
86                 f[i][j][k]=f[i-1][j][k]+value[i][k];
87                 if (j!=0)
88                     f[i][j][k]=min(f[i][j][k],ch[j-1]+value[i][k]);
89             }
90         }
91     }
92 
93     for (j=0;j<=g;j++)
94         for (k=0;k<802;k++)
95             pr=min(pr,f[n][j][k]);
96 
97     printf("%ld\n",pr);
98     return 0;
99 }

 


by lzu_cgb
share & spread idea

hiho_offer收割18_题解报告_差第四题