【2019.1.26】动规专题测试

T1 公交车换乘

  • 【题目描述】

  假设某条街上每一公里就有一个公共汽车站,并且乘车费用如下表:

  公里数     1       2       3       4       5       6       7       8       9       10

  费用         12     21     31     40     49     58     69     79     90     101

  而任意一辆汽车从不行驶超过10公里。某人想恰好行驶n公里,假设他可以任意次换车,请你帮他找到一种乘车方案,使得总费用最小。

  注意:10公里的费用比1公里小的情况是允许的。

  • 【输入】

  输入共两行,第一行为10个不超过200的整数,依次表示行驶1~10公里的费用,相邻两数间用一个空格隔开;第二行为某人想要行驶的公里数。

  • 【输出】

  输出仅一行,包含一个整数,表示行使这么远所需要的最小费用。

  • 【输入样例】

  12 21 31 40 49 58 69 79 90 101

  15

  • 【输出样例】

  147

  • 【数据规模】

  100%的数据满足:输入中所有数均为正整数,且不超过200

我能说我没读懂题意然后揣摩题揣摩了很久,然后对着样例尝试dou出147吗 我该滚回去学常规了 然后时间到,一解释,五分钟搞完

 1 /*
 2 id:gww
 3 language:
 4 啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊 
 5 */
 6 #include<bits/stdc++.h>
 7 using namespace std;
 8 const int N=100+20;
 9 const int M=500+20;
10 const int inf=0x3f3f3f3f;
11 int k[15],f[205],n;
12 int rd()
13 {
14     int x=0,w=0;char ch=0;
15     while(!isdigit(ch)) {w|=ch=='-';ch=getchar();}
16     while(isdigit(ch)) x=(x<<1)+(x<<3)+(ch^48),ch=getchar();
17     return w?-x:x;
18 }
19  
20 int main()
21 {
22     memset(f,inf,sizeof(f));
23     for(int i=1;i<=10;i++)
24     {k[i]=rd();f[i]=k[i];}
25     n=rd();
26     for(int i=1;i<=n;i++)
27     for(int j=1;j<=10;j++)
28     f[i+j]=min(f[i+j],f[i]+k[j]);
29     printf("%d",f[n]);
30     return 0;
31 }
View Code

T2 数字矩阵

  • 【题目描述】

  给一个由数字组成的矩形,每次可以向左、向右、向下走,求一条从最上层的任意一个点走到最下层的任意一个点最小数字和的路径,输出其值。

  • 【输入】

  输入第一行包含两个数n, m,表示矩形的行数和列数。

  接下来的n行每行有m个数,每个数表示矩形该位置上的值。

  • 【输出】

  输出最上层的任意一个点走到最下层的任意一个点的最小数字和的路径值。

  • 【输出样例】

  3 4

  9 9 1 9

  2 2 2 9

  1 9 9 9

  • 【输出样例】

  8

  • 【样例解释】

  9 9 1 9

  2 2 2 9

  1 9 9 9     是最优方案

向左向右各跑一遍 开始只跑了一遍然后又去写暴力炸了 就放弃了自我

 1 /*
 2 id:gww
 3 language:
 4 啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊 
 5 */
 6 #include<bits/stdc++.h>
 7 using namespace std;
 8 const int N=100+20;
 9 const int M=500+20;
10 const int inf=0x3f3f3f3f;
11 int n,m,mp[N][M],f[N][M],ans=inf;
12 bool vis[N][M];
13 int rd()
14 {
15     int x=0,w=0;char ch=0;
16     while(!isdigit(ch)) {w|=ch=='-';ch=getchar();}
17     while(isdigit(ch)) x=(x<<1)+(x<<3)+(ch^48),ch=getchar();
18     return w?-x:x;
19 }
20  
21 int main()
22 {
23     memset(f,inf,sizeof(f));
24     n=rd(),m=rd();
25     for(int i=1;i<=n;i++)
26     for(int j=1;j<=m;j++)
27     mp[i][j]=rd();
28     for(int i=1;i<=m;i++)
29     f[1][i]=mp[1][i];
30     for(int i=2;i<=n;i++)
31     {
32         for(int j=1;j<=m;j++)//向下走 向右
33         f[i][j]=min(f[i][j],min(f[i-1][j],f[i][j-1])+mp[i][j]);
34         for(int j=m;j>=1;j--)//向左 
35         f[i][j]=min(f[i][j],f[i][j+1]+mp[i][j]);
36     }
37     for(int i=1;i<=m;i++)
38     ans=min(ans,f[n][i]);
39     printf("%d",ans);
40     return 0;
41 }
View Code

T3 排列

  • 【题目描述】

  给一个数字串s和正整数d, 统计s有多少种不同的排列能被d整除(可以有前导0)。例如123434有90种排列能被2整除,其中末位为2的有30种,末位为4的有60种。

  • 【输入】

  输入第一行是一个整数T,表示测试数据的个数,以下每行一组s和d,中间用空格隔开。s保证只包含数字0, 1, 2, 3, 4, 5, 6, 7, 8, 9.

  • 【输出】

  每个数据仅一行,表示能被d整除的排列的个数。

  • 【输入样例】

  7

  000 1

  001 1

  1234567890 1

  123434 2

  1234 7

  12345 17

  12345678 29

  • 【输出样例】

  1

  3

  3628800

  90

  3

  6

  1398我写的时候忘了unique是怎么用的,排序后直接让ans=unique(a+1,a+1+n) 应该是ans=unique(a+1,a+1+n)-a 然后就一直报错QAQ硬刚好久

  • 关于next_permutation
 1 /*
 2 id:gww
 3 language:
 4 啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊 
 5 */
 6 #include<bits/stdc++.h>
 7 using namespace std;
 8 int rd()
 9 {
10     int x=0,w=0;char ch=0;
11     while(!isdigit(ch)) {w|=ch=='-';ch=getchar();}
12     while(isdigit(ch)) x=(x<<1)+(x<<3)+(ch^48),ch=getchar();
13     return w?-x:x;
14 }
15 int main()
16 {
17     int  a[]={5,4,9};
18     sort(a,a+3);
19     do
20     {
21         for(int i=0;i<=2;i++)
22         printf("%d ",a[i]);
23         printf("\n");
24     }while(next_permutation(a,a+3));
25     return 0;
26 }
next_permutation实现全排列

f[s][k]表示已选取集合s中的数字%d的余数为k的情况数

然后就是去重操作

若求111的排列有多少能被3整除
那么(s是二进制下的值)
f[000][0]=1  f[001][1]=1  f[010][1]=1  f[011][2]=2
f[100][1]=1  f[101][2]=2  f[110][2]=2  f[111][0]=6
但是实际上只有111一种
也就是说同种数字的不同选择顺序被重复计算了,如果我们强制每个相同数字,在得到答案中必须按照原来的情况
例如,原数为141被3整除的情况,表示141时,下标序列一定是132,而不能是312
 1 /*
 2 id:gww
 3 language:
 4 啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊 
 5 */
 6 #include<bits/stdc++.h>
 7 using namespace std;
 8 const int N=15;
 9 const int inf=0x3f3f3f3f;
10 char s[N];
11 int mo,a[N],f[1<<N][1000+5];
12 int rd()
13 {
14     int x=0,w=0;char ch=0;
15     while(!isdigit(ch)) {w|=ch=='-';ch=getchar();}
16     while(isdigit(ch)) x=(x<<1)+(x<<3)+(ch^48),ch=getchar();
17     return w?-x:x;
18 }
19 
20 
21 int main()
22 {
23     int t=rd();
24 
25     while(t--)
26     {
27         memset(f,0,sizeof(f));
28         f[0][0]=1;
29         scanf("%s",s);mo=rd();
30         int ls=strlen(s);
31         for(int i=0;i<ls;i++)
32         if(s[i]>='0'&&s[i]<='9')
33         a[i+1]=s[i]-'0';
34         for(int st=0;st<(1<<ls);st++)//枚举状态
35         for(int k=0;k<=mo;k++)//枚举余数
36         {
37             if(f[st][k])
38             {
39                 for(int i=1;i<=ls;i++)//枚举数
40                 if((st&(1<<(i-1)))==0)//如果没有放入
41                 f[st|(1<<(i-1))][(k*10+a[i])%mo]+=f[st][k];
42             }
43         }
44         int ans=f[(1<<ls)-1][0];
45         for(int i=0;i<=9;i++)//去重
46         {
47             int cnt=0;
48             for(int j=1;j<=ls;j++)
49             if(a[j]==i) cnt++;
50             int r=1;
51             for(int k=1;k<=cnt;k++)
52             r*=k;
53             ans/=r;
54          } 
55          printf("%d\n",ans);
56     }
57     return 0;
58 }
动规

[SCOI2007]排列  原题可以用暴力过QAQ

 1 #include<bits/stdc++.h>
 2 using namespace std;
 3 long long n,m,i,j,k,hrb[15],s=0,t;
 4 char lxy[15];
 5 int main()
 6 {
 7     scanf("%lld",&t);
 8     while(t)
 9     {
10         scanf("%s%lld",lxy,&n);
11         m=strlen(lxy);
12         for(i=0;i<m;i++)
13         hrb[i+1]=lxy[i]-'0';//字符转数字
14         sort(hrb+1,hrb+m+1);
15         /*要排序,因为要递增序列,其实如果你够优秀(闲),你可以用next_permutation和prev_permutation各求一次,在把结果加起来*/
16         s=0;//记得清0
17         do
18         {
19             long long ss=0;
20             for(i=1;i<=m;i++)
21             ss=ss*10+hrb[i];//求总值,因为函数也会修改数组
22             if(ss%n==0)s++;
23         }
24         while(next_permutation(hrb+1,hrb+m+1));
25         //当排列没有后(即变为了递减数列)返回0,就可以结束循环
26         printf("%lld\n",s);//输出答案
27         t--;
28     }
29     return 0;
30 }
抄来的stl暴力

总结

  • QAQ我还是太菜了

猜你喜欢

转载自www.cnblogs.com/lxyyyy/p/10324161.html