題目鏈接
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),隊首會不斷去洗澡,交談對象改變又產生幸福值。
總共有五個人,給出兩兩交談產生的幸福值。求如何排列可以產生最大幸福值,輸出最大幸福值。
例:
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
32
In the first sample, the optimal arrangement of the line is 23154. In this case, the total happiness equals:
代碼:
#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[N]表示所走的邊的值不大於k的所有方法,dp2[N]表示所走的邊的值小於k的所有方法。dp1[n]-dp2[n]即爲所求。
代碼:
#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[n]<<ends<<dp2[n]<<endl;
int ans=(dp1[n]-dp2[n]+MOD)%MOD;//由於取模會造成dp1[n]<dp2[n],所以先加一個MOD,防止爲負。
printf("%d\n",ans);
}
return 0;
}
C 【小結】:對於此題的dp[] 放入的物品即使是相同的,但如果順序不同也看做不同的方法。而一般的揹包將這看做相同的方法。i,j循環次序的不同導致了dp不同的含義。