http://acm.timus.ru/problem.aspx?space=1&num=1611
DP 递推
显然这个题是可能有多组解的 求最优解+记录路径即可
当 i 个 conductors 和 j 个 dodgers 时 最后的人可能是 conductor 也可能是 dodger 枚举这两种情况最优即可
代码及其注释:
#include <iostream>
#include <cstdio>
#include <cstring>
#include <string>
#include <queue>
#include <vector>
#include <algorithm>
#define LL long long
//#pragma comment(linker, "/STACK:1024000000,1024000000")
using namespace std;
const int N=10005;
const int M=55;
int ans[N][M];//i 个conductors 和 j 个dodgers 时的最优解
int fx[N][M];//最优解的向前指针
int fy[N][M];
string s;//输入
void dfs(int l1,int l2)//答案输出
{
if(fy[l1][l2]>=1)
dfs(fx[l1][l2],fy[l1][l2]);
if(fy[l1][l2]==l2-1)
{cout<<" "<<(l1+l2);}
}
int main()
{
//freopen("data.txt","r",stdin);
int n,m;
while(cin>>n>>m)
{
cin>>s;
for(int j=0;j<=m;++j)
{ans[0][j]=j/10;fx[0][j]=0;fy[0][j]=j-1;}//初始化
for(int i=1;i<=n;++i)
{
ans[i][0]=ans[i-1][0];//初始化
if(i%10==0&&s[i-1]=='1')
++ans[i][0];
}
for(int i=1;i<=n;++i)
{
for(int j=1;j<=m;++j)
{
//第一种是最后一个是conductor 的情况
ans[i][j]=ans[i-1][j];
if(s[i-1]=='1'&&(i+j)%10==0)
++ans[i][j];
fx[i][j]=i-1;
fy[i][j]=j;
//第二种情况是最后是dodger 的情况
int temp=((i+j)%10)?0:1;
if(ans[i][j-1]+temp<ans[i][j])
{
ans[i][j]=ans[i][j-1]+temp;
fx[i][j]=i;
fy[i][j]=j-1;
}
}
}
int l2=0;
for(int j=1;j<=m;++j)
if(ans[n][j]<ans[n][l2])
l2=j;
cout<<ans[n][l2]<<endl;
cout<<l2;
dfs(n,l2);
}
return 0;
}
浙公网安备 33010602011771号