码迷,mamicode.com
首页 > 其他好文 > 详细

NOIP 2001 提高组 题解

时间:2016-07-30 08:04:58      阅读:162      评论:0      收藏:0      [点我收藏+]

标签:

No 1. 一元三次方程求解

https://vijos.org/p/1116

看见有人认真推导了求解公式,然后猥琐暴力过的同学们在一边偷笑~~~

数据小 暴力枚举即可

 1 double a,b,c,d;
 2 double x;
 3 
 4 int main()
 5 {
 6     ios_base::sync_with_stdio(0);
 7     
 8     cin>>a>>b>>c>>d;
 9     
10     for(double i=-10000;i<=10000;i+=1)
11     {
12         x=i/100;
13         
14         if(abs(a*x*x*x+b*x*x+c*x+d)<0.01)
15         {
16             printf("%.2f ",x);
17         }
18     }
19 
20     return 0;
21 }

 

No 2. 数的划分

https://vijos.org/p/1117

dp/dfs

dp

用f(i,j)表示i这个数分成k份有多少种分法

毫无疑问 

f[i][j]=f[i-1][j-1]+f[i-j][j];

因为 f(i,j) 可以从 f(i-1,j-1)推出

又要保持不下降的分划

所以可以从f(i-j,j)推出

 

 1 int n,k;
 2 int f[222][222];
 3 
 4 void init()
 5 {
 6     cin>>n>>k;
 7     
 8     for(int i=1;i<=n;i++)
 9     {
10         for(int j=1;j<=i;j++)
11         {
12             f[i][j]=inf;
13         }
14     }
15     
16     for(int i=1;i<=n;i++)
17     {
18         f[i][1]=1;
19     }
20 }
21 
22 int main()
23 {
24     init();
25     
26     for(int i=2;i<=n;i++)
27     {
28         for(int j=2;j<=i;j++)
29         {
30             f[i][j]=f[i-1][j-1]+f[i-j][j];
31         }
32     }
33     
34     cout<<f[n][k]<<endl;
35     
36     return 0;
37 }

 

dfs

暴力枚举

只要不下降+剪枝就可以了

 

 1 int n,k;
 2 int ans;
 3 
 4 void dfs(int nw,int sum,int num)
 5 {
 6     if(num==k)
 7     {
 8         if(sum==n)
 9         {
10             ans++;
11         }
12         else
13         {
14             return;
15         }
16     }
17     
18     if(sum==n)
19     {
20         return;
21     }
22     
23     for(int i=nw;i<=n-sum;i++)
24     {
25         dfs(i,sum+i,num+1);
26     }
27     
28     return;
29 }
30 
31 int main()
32 {
33     ios_base::sync_with_stdio(0);
34     
35     cin>>n>>k;
36     
37     for(int i=1;i<=n/2;i++)
38     {
39         dfs(i,i,1);
40     }
41         
42     cout<<ans<<endl;
43 
44     return 0;
45 }

 

No 3. 统计单词个数

https://vijos.org/p/1118

dp

这几年dp考的好多啊

这题题解我真的不会写 我的写法我自己都看不懂

复制一段

 划分这个DP,很基础。

 然后,是sum[i][j],第i个字母到第j个字母一共可以形成多少个单词,ccy也用的Dp。

 sum[i][j]=sum[i][-1]+(包含可以添加最后一个字母j的单词的总个数)。

 ccy,WA在……比如现在可以添加一个新单词,k到j,但是,若果以k为起点,在sum[i][j-1]中已经有过单词,该新单词就不添加。于是乎,ccy光荣地WA掉一个点,因为,

 那个点有两个相同的单词,我就扩展了两次。

 

 1 string s;
 2 int slen;
 3 string words[maxm];
 4 int wordslen[maxm];
 5 int f[maxn][maxm];
 6 int sum[maxn][maxn];
 7 int n,k,m;
 8  
 9 void init()
10 {
11     string tmp;
12     cin>>n>>k;
13     for (int i=1;i<=n;i++)
14     {
15         cin>>tmp;
16         s+=tmp;
17     }
18     slen=s.size();
19     cin>>m;
20     for (int i=1;i<=m;i++)
21     {
22         cin>>words[i];
23         wordslen[i]=words[i].size();
24     }
25 }
26  
27 int add(int l,int r)
28 {
29     int ans=0;
30     if (r-1>=0) ans=sum[l][r-1];
31     bool vis[maxn]={0};
32     for (int i=1;i<=m;i++)
33     {
34         int qd=r-wordslen[i]+1;
35         if (qd<l) continue;
36         if (qd==s.find(words[i],qd))
37         {
38             if (vis[qd]) continue;
39             vis[qd]=1;
40             ans++;
41             for (int j=1;j<=m;j++)
42             {
43                 int dq=r-wordslen[j];
44                 if (dq==qd)
45                     if (dq==s.find(words[j],dq))
46                     {
47                         ans--;
48                         break;
49                     }
50             }
51         }
52     }
53     return ans;
54 }
55  
56 void gsum()
57 {
58     for (int i=0;i<=slen-1;i++)
59         for (int j=i;j<=slen-1;j++)
60         {
61             sum[i][j]=add(i,j);
62         }
63 }
64  
65 void work()
66 {
67     for (int i=0;i<=slen-2;i++)
68         f[i][1]=sum[0][i];
69     for (int i=0;i<=slen-2;i++)
70         for (int j=2;j<=min(k-1,i+1);j++)
71             for (int u=j-2;u<=i-1;u++)
72                 f[i][j]=max(f[i][j],f[u][j-1]+sum[u+1][i]);
73     int ans=0;
74     if (k==0)
75         ans=sum[0][slen-1];
76     else
77         for (int i=k-1;i<=slen-2;i++)
78             ans=max(ans,f[i][k-1]+sum[i+1][slen-1]);
79     printf("%d\n",ans);
80 }
81  
82 int main()
83 {
84     int qn;
85     qn=1;
86     while(qn--)
87     {
88         init();
89         gsum();
90         work();    
91     }
92         
93     return 0;
94 }

 

先写这么多 第四题下午再写

Bye~~~

NOIP 2001 提高组 题解

标签:

原文地址:http://www.cnblogs.com/nflslzt/p/5720130.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!