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