您的位置:首页 > 其它

CodeForces 2B The least round way(dp+数学)

2016-02-13 19:43 453 查看
题意:

给你一个矩阵,让你在里面找一条路径,使得这条路径上的数相乘之后的末尾0
最少。
一看像是一个dp的题,但是还是需要一点数学在里面(数学渣伤不起),末尾
0最少,意味着路径上的数的2和5因子要尽量少,所以我们需要找两条路,一条
是2最少的,一条是5最少的,那么答案就是min(a,b),为什么呢?我们设想一
下,2最少的那条路保证了其他路上的的2都比这个多,5也是同理,又因为这
两条路一般不会是一条,那么对应的路上的2和5肯定不是最少的,所以答案
出来了。所以这个问题就转化成一个dag上的最短路了,bfs就行。
然而这个题目还是有坑的,因为可能会输入0,这也就意味着连乘之后都是0,
所以,我们需要看一下有0的特殊情况下,答案是1,还要和另外两个比较。


代码:

//
//  Created by  CQU_CST_WuErli
//  Copyright (c) 2016 CQU_CST_WuErli. All rights reserved.
//
#include <iostream>
#include <cstring>
#include <cstdio>
#include <cstdlib>
#include <cctype>
#include <cmath>
#include <string>
#include <vector>
#include <list>
#include <map>
#include <queue>
#include <stack>
#include <set>
#include <algorithm>
#include <sstream>
#include <assert.h>
#define CLR(x) memset(x,0,sizeof(x))
#define OFF(x) memset(x,-1,sizeof(x))
#define MEM(x,a) memset((x),(a),sizeof(x))
#define BUG cout << "I am here" << endl
#define lookln(x) cout << #x << "=" << x << endl
#define SI(a) scanf("%d",&a)
#define SII(a,b) scanf("%d%d",&a,&b)
#define SIII(a,b,c) scanf("%d%d%d",&a,&b,&c)
#define rep(flag,start,end) for(int flag=start;flag<=end;flag++)
#define Rep(flag,start,end) for(int flag=start;flag>=end;flag--)
#define Lson l,mid,rt<<1
#define Rson mid+1,r,rt<<1|1
#define Root 1,n,1
#define BigInteger bign
const int MAX_L=2005;// For BigInteger
const int INF_INT=0x3f3f3f3f;
const long long INF_LL=0x7fffffff;
const int MOD=1e9+7;
const double eps=1e-9;
const double pi=acos(-1);
typedef long long  ll;
using namespace std;

const int N=1010;

int a

;
int mp[2]

;
int n;
int dp[2]

;
char pre[2]

;
int vis

;

struct Sta
{
int x,y;
};

int main(int argc, char const *argv[]) {
#ifdef LOCAL
freopen("C:\\Users\\john\\Desktop\\in.txt","r",stdin);
// freopen("C:\\Users\\john\\Desktop\\out.txt","w",stdout);
#endif
while(SI(n)==1) {
CLR(mp);
int flag=0;
Sta zero;
rep(i,1,n) rep(j,1,n) {
int x;SI(x);
a[i][j]=x;
int tmp=x;
if (x==0) {
zero.x=i;zero.y=j;
flag=1;
continue;
}
while (tmp%2==0) mp[0][i][j]++,tmp/=2;
while (x%5==0) mp[1][i][j]++,x/=5;
}
int dir[2][2]={1,0,0,1};
for (int z=0;z<2;z++) for (int i=1;i<=n;i++) for (int j=1;j<=n;j++) dp[z][i][j]=INF_INT;
for (int z=0;z<2;z++) {
CLR(vis);CLR(pre[z]);
queue<Sta> q;
vis[1][1]=1;
q.push(Sta{1,1});
dp[z][1][1]=mp[z][1][1];
while (q.size()) {
Sta now=q.front();q.pop();
for (int i=0;i<2;i++) {
int nx=now.x+dir[i][0],ny=now.y+dir[i][1];
if (nx<1 || ny<1 || nx>n || ny>n) continue;
if (dp[z][nx][ny]>dp[z][now.x][now.y]+mp[z][nx][ny]) {
dp[z][nx][ny]=dp[z][now.x][now.y]+mp[z][nx][ny];
pre[z][nx][ny]=i==0?'D':'R';
if (!vis[nx][ny]) {
vis[nx][ny]=1;
q.push(Sta{nx,ny});
}
}
}
}
}
vector<char> ans;
if (flag && min(dp[0]

,dp[1]

)>1) {
cout << 1 << endl;
int aa=zero.x,bb=zero.y;
for (int i=1;i<aa;i++) ans.push_back('D');
for (int i=1;i<bb;i++) ans.push_back('R');
for (int i=aa+1;i<=n;i++) ans.push_back('D');
for (int i=bb+1;i<=n;i++) ans.push_back('R');
for (int i=0;i<ans.size();i++) cout << ans[i];
cout << endl;
}
else {
cout << min(dp[0]

,dp[1]

) << endl;
int pos=dp[0]

<dp[1]

?0:1;
int nx=n,ny=n;
while(1) {
ans.push_back(pre[pos][nx][ny]);
if (pre[pos][nx][ny]=='D') {
nx--;
}
else ny--;
if (nx==1 && ny==1) break;
}
reverse(ans.begin(),ans.end());
for (int i=0;i<ans.size();i++) cout << ans[i];
cout << endl;
}
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  codeforces 数学 dp