A:地砖问题 简单bfs
B:最小花费 dfs+dijkstra
C:回文串 动态规划
D:有序合并 数组排序
E:十六进制转换 字符串问题
http://39.106.164.46/problem.php?id=1110
题意:
求可以走过最多的黑砖个数。
思路:
简单的bfs。
AC代码:
#include
#include
#include
#include
#include
#include
#include
#include
#include
#define MAX 30
#define INF 0x3f3f3f3f
typedef long long ll;
using namespace std;
int n,m;//n行,m列
char ch[MAX][MAX];
int dir[4][2]={{0,1},{1,0},{-1,0},{0,-1}},visit[MAX][MAX];
struct node{
int x,y;
node(int xx,int yy){
x=xx;
y=yy;
}
};
bool judge(int x,int y){
if(x<0||x>n-1||y<0||y>m-1) return false;
return true;
}
int bfs(int x,int y){
int sum=0;
queue<node> q;
node t(x,y);
q.push(t);
visit[x][y]=1;
while(!q.empty()){
node top=q.front();
q.pop();
int x=top.x;
int y=top.y;
if(ch[x][y]=='@'||ch[x][y]=='.') sum++;
for(int i=0;i<4;i++){
int xx=x+dir[i][0];
int yy=y+dir[i][1];
if(judge(xx,yy)&&visit[xx][yy]==0&&ch[xx][yy]=='.'){
node tmp(xx,yy);
visit[xx][yy]=1;
q.push(tmp);
}
}
}
return sum;
}
int main(){
while(scanf("%d %d",&m,&n)!=EOF){
if(n==0&&m==0) return 0;
memset(visit,0,sizeof(visit));
for(int i=0;i<n;i++){
scanf("%s",&ch[i]);
}
int x,y;
for(int i=0;i<n;i++){
for(int j=0;j<m;j++){
if(ch[i][j]=='@'){
x=i,y=j;
}
}
}
int res=bfs(x,y);
printf("%d\n",res);
}
return 0;
}
http://39.106.164.46/problem.php?id=1111
题意:
Dijkstra + DFS模板题。
题目的意思其实是只能沿着一条路径转账,那么从A到B,我们可以找出所有的最短路径,一次dijkstra即可,在路径花费最小的情况下,可以再用一次dfs找出路径数量最多的那一条路径,这样就能保证损失的钱最少,那么A转给B的钱也就是最少的。
AC代码:
#include
#include
#include
#include
#include
#include
#include
#include
#include
#define MAX 2005
#define INF 0x3f3f3f3f
typedef long long ll;
using namespace std;
int n,m;
int mp[MAX][MAX],dis[MAX],vis[MAX];
vector<int> pre[MAX];
vector<int> path,tmppath;
int start,goal,ans=-1;
void dijkstra(int s){
for(int i=0;i<=n;i++){
vis[i]=0;
dis[i]=INF;
}
dis[s]=0;
for(int i=0;i<n;i++){
int u=-1,minl=INF;
for(int j=1;j<=n;j++){
if(dis[j]<minl&&vis[j]==0){
minl=dis[j];
u=j;
}
}
if(u==-1) break;
vis[u]=1;
for(int v=1;v<=n;v++){
if(vis[v]==0&&mp[u][v]!=INF){
if(dis[v]>dis[u]+mp[u][v]){
dis[v]=dis[u]+mp[u][v];
pre[v].clear();
pre[v].push_back(u);
}else if(dis[v]==dis[u]+mp[u][v]){
pre[v].push_back(u);
}
}
}
}
}
void dfs(int v){
tmppath.push_back(v);
if(v==start){//当最短距离相同时,选择路径最多的一条
int tmp=tmppath.size();
if(ans<tmp){
ans=tmp;
path=tmppath;
}
tmppath.pop_back();
return;
}
for(int i=0;i<pre[v].size();i++){
dfs(pre[v][i]);
}
tmppath.pop_back();
}
int main(){
while(scanf("%d %d",&n,&m)!=EOF){
for(int i=0;i<MAX;i++){//初始化
for(int j=0;j<MAX;j++){
mp[i][j]=INF;
}
}
int a,b,len;
for(int i=0;i<m;i++){
scanf("%d %d %d",&a,&b,&len);
mp[a][b]=mp[b][a]=len;
}
scanf("%d %d",&start,&goal);
dijkstra(start);
ans=-1;
dfs(goal);
double res=100.0;
int now=path[0];
for(int i=1;i<path.size();i++){
int rate=mp[now][path[i]];
double r=(double)rate/100;
res=res/(1.0-r);
now=path[i];
}
printf("%.8lf\n",res);
}
return 0;
}
http://39.106.164.46/problem.php?id=1112
思路:
其实就是简单的动态规划。枚举子串的长度即可。
AC代码:
#include
#include
#include
#include
#include
#include
#include
#include
#include
#define MAX 5005
#define INF 0x3f3f3f3f
typedef long long ll;
using namespace std;
string s;
int dp[MAX][MAX];
int main(){
while(cin>>s){
memset(dp,0,sizeof(dp));//初始化
int len=s.length(),ans=0;//ans记录总的连续回文子串个数
for(int i=0;i<len;i++){
dp[i][i]=1;
ans++;
if(i<len-1){
if(s[i]==s[i+1]){
ans++;
dp[i][i+1]=1;
}
}
}
//状态转移方程
for(int l=3;l<=len;l++){//枚举子串的长度
for(int i=0;i+l-1<len;i++){
int j=i+l-1;
if(s[i]==s[j]&&dp[i+1][j-1]==1){
ans++;
dp[i][j]=1;
}
}
}
printf("%d\n",ans);
}
return 0;
}
http://39.106.164.46/problem.php?id=1113
思路:
注意读数的方式,用一个数组存储读进来的两行数,然后排序输出即可。
AC代码:
#include
#include
#include
#include
#include
#include
#include
#include
#include
#define MAX 5005
#define INF 0x3f3f3f3f
typedef long long ll;
using namespace std;
int n,m;
vector<int> vec;
int num,cnt=0;
int main(){
while(scanf("%d",&n)!=EOF){
cnt++;
for(int i=0;i<n;i++){
scanf("%d",&num);
vec.push_back(num);
}
if(cnt==2){
sort(vec.begin(),vec.end());
for(int i=0;i<vec.size();i++){
printf("%s%d",i==0?"":" ",vec[i]);
}
cout<<endl;
vec.clear();
cnt=0;
}
}
return 0;
}
http://39.106.164.46/problem.php?id=1114
思路:
将一个不超过100000位的十六进制数,转换成八进制数。使用map,首先可以将十六进制数转化为二进制数,然后补充前导0至长度为3的倍数,然后将这个二进制数转化为八进制数,最后不输出前导0即可。
AC代码:
#include
#include
#include
#include
#include
#include
#include
#include
#include
#define MAX 5005
#define INF 0x3f3f3f3f
typedef long long ll;
using namespace std;
string s;
map<char,string> mp1;
map<string,char> mp2;
int main(){
mp1['0']="0000";mp1['1']="0001";mp1['2']="0010";mp1['3']="0011";
mp1['4']="0100";mp1['5']="0101";mp1['6']="0110";mp1['7']="0111";
mp1['8']="1000";mp1['9']="1001";mp1['A']="1010";mp1['B']="1011";
mp1['C']="1100";mp1['D']="1101";mp1['E']="1110";mp1['F']="1111";
mp2["000"]='0';mp2["001"]='1';mp2["010"]='2';mp2["011"]='3';
mp2["100"]='4';mp2["101"]='5';mp2["110"]='6';mp2["111"]='7';
while(cin>>s){
string res="",tmp="";
int len=s.length();
for(int i=0;i<len;i++){
tmp+=mp1[s[i]];
}
if(tmp.size()%3==1){//若余1,这说明差2位,前面补2个0,补成3的倍数
tmp="00"+tmp;
}else if(tmp.size()%3==2){//若余2,这说明差1位,前面补1个0
tmp="0"+tmp;
}
for(int i=0;i<tmp.size();i+=3){
res=res+mp2[tmp.substr(i,3)];
}
int flag=0;
for(int i=0;i<res.size();i++){
if(res[i]=='0'&&flag==0) continue;
flag=1;
cout<<res[i];
}
cout<<endl;
}
return 0;
}