Codeforces Round #247 (Div. 2)a.Black Square,b.Shower Line,c.k-Tree前三题
2014-05-22 13:44
405 查看
题目链接
a.Black Square: http://codeforces.com/contest/431/problem/A
b.Shower Line: http://codeforces.com/contest/431/problem/B
c.k-Tree http://codeforces.com/contest/431/problem/C
A【题意】(水)
顺序输入四个数,第i个数表示去掉i需要的能量。第二行输入输入一串数(1-4以内的数),求去掉这串数所需的能量。
代码:
#include<iostream>
#include<cstdio>
using namespace std;
char s[100010];
int main()
{
int A[10];
while(scanf("%d%d%d%d",&A[1],&A[2],&A[3],&A[4])!=EOF)
{
scanf("%s",s);
int sum=0;
for(int i=0;s[i]!=0;i++)
sum+=A[s[i]-'0'];
printf("%d\n",sum);
}
return 0;
}
B【题意】(水)
一列人排队洗澡,前后的两个人相互交谈产生幸福值(如果有人当前没有交谈对象,则产生幸福值为0),队首会不断去洗澡,交谈对象改变又产生幸福值。
总共有五个人,给出两两交谈产生的幸福值。求如何排列可以产生最大幸福值,输出最大幸福值。
例:
Sample test(s)
input
output
In the first sample, the optimal arrangement of the line is 23154. In this case, the total happiness equals:
(g23 + g32 + g15 + g51) + (g13 + g31 + g54 + g45) + (g15 + g51) + (g54 + g45) = 32
由于只有5个人枚举即可。
代码:
#include<cstdio>
#include<iostream>
#include<cstring>
using namespace std;
int vis[10];
int G[10][10];
int pre[10];//记录所选的人
int dfs(int p)
{
int ans=0;
if(p>5)
{
for(int i=1;i<=5;i++)
ans+=G[pre[i]][pre[i+1]]+G[pre[i+1]][pre[i]]+G[pre[i+2]][pre[i+3]]+G[pre[i+3]][pre[i+2]];
return ans;
}
for(int i=1;i<=5;i++)
{
if(!vis[i])
{
vis[i]=1;
pre[p]=i;
ans=max(ans,dfs(p+1));
vis[i]=0;
}
}
return ans;
}
int main()
{
int i,j;
memset(vis,0,sizeof(vis));
for(i=1;i<=5;i++)
for(j=1;j<=5;j++)
scanf("%d",&G[i][j]);
int ans=0;
for(i=1;i<=5;i++)
{
vis[i]=1;
pre[1]=i;
ans=max(ans,dfs(2));
vis[i]=0;
}
printf("%d\n",ans);
return 0;
}
c【题意】
给出一个每个节点有k个儿子的树。每个节点到第i个儿子的值为i。求有多少种方法从根开始向下走,得到的总值为n(至少经过一条值不小于d的边)。
【思路】
变形的背包。dp1
表示所走的边的值不大于k的所有方法,dp2
表示所走的边的值小于k的所有方法。dp1
-dp2
即为所求。
代码:
#include<cstdio>
#include<cstring>
#include<iostream>
using namespace std;
int dp1[110],dp2[110];
const int MOD = 1000000007;
int main()
{
int n,k,d;
while(scanf("%d%d%d",&n,&k,&d)!=EOF)
{
memset(dp1,0,sizeof(dp1));
memset(dp2,0,sizeof(dp2));
dp1[0]=dp2[0]=1;
for(int i=1;i<=n;i++)
{
for(int j=1;j<=k;j++)
{
if(i>=j)
{
dp1[i]=(dp1[i]+dp1[i-j])%MOD;
if(j<d)
dp2[i]=(dp2[i]+dp2[i-j])%MOD;
}
}
}
//cout<<dp1
<<ends<<dp2
<<endl;
int ans=(dp1
-dp2
+MOD)%MOD;//由于取模会造成dp1
<dp2
,所以先加一个MOD,防止为负。
printf("%d\n",ans);
}
return 0;
}
C 【小结】:对于此题的dp[] 放入的物品即使是相同的,但如果顺序不同也看做不同的方法。而一般的背包将这看做相同的方法。i,j循环次序的不同导致了dp不同的含义。
a.Black Square: http://codeforces.com/contest/431/problem/A
b.Shower Line: http://codeforces.com/contest/431/problem/B
c.k-Tree http://codeforces.com/contest/431/problem/C
A【题意】(水)
顺序输入四个数,第i个数表示去掉i需要的能量。第二行输入输入一串数(1-4以内的数),求去掉这串数所需的能量。
代码:
#include<iostream>
#include<cstdio>
using namespace std;
char s[100010];
int main()
{
int A[10];
while(scanf("%d%d%d%d",&A[1],&A[2],&A[3],&A[4])!=EOF)
{
scanf("%s",s);
int sum=0;
for(int i=0;s[i]!=0;i++)
sum+=A[s[i]-'0'];
printf("%d\n",sum);
}
return 0;
}
B【题意】(水)
一列人排队洗澡,前后的两个人相互交谈产生幸福值(如果有人当前没有交谈对象,则产生幸福值为0),队首会不断去洗澡,交谈对象改变又产生幸福值。
总共有五个人,给出两两交谈产生的幸福值。求如何排列可以产生最大幸福值,输出最大幸福值。
例:
Sample test(s)
input
0 0 0 0 9 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 7 0 0 0 0
output
32
In the first sample, the optimal arrangement of the line is 23154. In this case, the total happiness equals:
(g23 + g32 + g15 + g51) + (g13 + g31 + g54 + g45) + (g15 + g51) + (g54 + g45) = 32
由于只有5个人枚举即可。
代码:
#include<cstdio>
#include<iostream>
#include<cstring>
using namespace std;
int vis[10];
int G[10][10];
int pre[10];//记录所选的人
int dfs(int p)
{
int ans=0;
if(p>5)
{
for(int i=1;i<=5;i++)
ans+=G[pre[i]][pre[i+1]]+G[pre[i+1]][pre[i]]+G[pre[i+2]][pre[i+3]]+G[pre[i+3]][pre[i+2]];
return ans;
}
for(int i=1;i<=5;i++)
{
if(!vis[i])
{
vis[i]=1;
pre[p]=i;
ans=max(ans,dfs(p+1));
vis[i]=0;
}
}
return ans;
}
int main()
{
int i,j;
memset(vis,0,sizeof(vis));
for(i=1;i<=5;i++)
for(j=1;j<=5;j++)
scanf("%d",&G[i][j]);
int ans=0;
for(i=1;i<=5;i++)
{
vis[i]=1;
pre[1]=i;
ans=max(ans,dfs(2));
vis[i]=0;
}
printf("%d\n",ans);
return 0;
}
c【题意】
给出一个每个节点有k个儿子的树。每个节点到第i个儿子的值为i。求有多少种方法从根开始向下走,得到的总值为n(至少经过一条值不小于d的边)。
【思路】
变形的背包。dp1
表示所走的边的值不大于k的所有方法,dp2
表示所走的边的值小于k的所有方法。dp1
-dp2
即为所求。
代码:
#include<cstdio>
#include<cstring>
#include<iostream>
using namespace std;
int dp1[110],dp2[110];
const int MOD = 1000000007;
int main()
{
int n,k,d;
while(scanf("%d%d%d",&n,&k,&d)!=EOF)
{
memset(dp1,0,sizeof(dp1));
memset(dp2,0,sizeof(dp2));
dp1[0]=dp2[0]=1;
for(int i=1;i<=n;i++)
{
for(int j=1;j<=k;j++)
{
if(i>=j)
{
dp1[i]=(dp1[i]+dp1[i-j])%MOD;
if(j<d)
dp2[i]=(dp2[i]+dp2[i-j])%MOD;
}
}
}
//cout<<dp1
<<ends<<dp2
<<endl;
int ans=(dp1
-dp2
+MOD)%MOD;//由于取模会造成dp1
<dp2
,所以先加一个MOD,防止为负。
printf("%d\n",ans);
}
return 0;
}
C 【小结】:对于此题的dp[] 放入的物品即使是相同的,但如果顺序不同也看做不同的方法。而一般的背包将这看做相同的方法。i,j循环次序的不同导致了dp不同的含义。
相关文章推荐
- Codeforces Round #247(Div. 2) B. Shower Line 暴力
- Codeforces Round #247 (Div. 2) B. Shower Line(简单模拟)
- DIV横排/竖排滚动(white-space/::-webkit-scrollbar的使用技巧以及display: inline-block的选择)支持手势
- 数论+快速幂 SRM 661 Div1 450: ColorfulLineGraphs
- Codeforces Round #358 (Div. 2) C. Alyona and the Tree 水题
- Codeforces Round #363 (Div. 2) D Fix a Tree(并查集)
- Codeforces Round #358 (Div. 2) Alyona and the Tree
- Codeforces Round #358 (Div. 2)——C. Alyona and the Tree(树的DFS+逆向思维)
- codeforces #345 (Div. 1) D. Zip-line (线段树+最长上升子序列)
- Codeforces Round #170 (Div. 1) E.Binary Tree on Plane
- hdu 5423 Rikka with Tree(dfs)bestcoder #53 div2 1002
- Codeforces Round #395 (Div. 2) C. Timofey and a tree(树的基础应用)
- Codeforces Round #263 Div.1 B Appleman and Tree --树形DP【转】
- Codeforces Round #397 by Kaspersky Lab and Barcelona Bootcamp (Div. 1 + Div. 2 combined) E. Tree Folding
- [树的直径] Codeforces 804D Round #411 (Div. 1) D. Expected diameter of a tree
- Codeforces Round #339 (Div. 2) A. Link/Cut Tree
- Codeforces Round #339 (Div. 2) A. Link/Cut Tree - Codeforces(思维)
- DIV CSS display (block none inline)属性的用法
- Codeforces Round #430 (Div. 2) C. Ilya And The Tree
- Codeforces Round #430 (Div. 2) C. Ilya And The Tree dfs+set