您的位置:首页 > 其它

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
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