2014上海全國邀請賽題解 HDOJ 5090-5099
阿新 • • 發佈:2019-02-08
HDOJ 5090
水題,從小到大排序,可以填充達到符合條件的,先填充好,填充之後進行調整。
#include <cstdio> #include <cmath> #include <queue> #include <map> #include <vector> #include <cstring> #include <algorithm> using namespace std; const int MAXN = 1e2+10; int t, n, k, ia[MAXN]; int main() { scanf("%d", &t); while(t--) { scanf("%d%d", &n, &k); bool flag = true; for(int i=1; i<=n; ++i) { scanf("%d", ia+i); } sort(ia+1, ia+n+1); for(int i=1; i<=n; ++i) { if(i < ia[i]) { flag = false; break; } if(i == ia[i]) { continue; } if(0 == (i-ia[i])%k) { ia[i] = i; } else { int tp = 1; for(int j=i+1; j<=n; ++j) { if(0 == (j-ia[i])%k) { ia[i] = j; tp = 0; --i; break; } } if(tp) { flag = false; break; } } sort(ia+1, ia+n+1); } printf("%s\n", flag ? "Jerry" : "Tom"); } return 0; }
HDOJ 5092
題意:每行取一個數,使總和最小,取了mp[i][j]之後,只能在該點左下,正下,右下三個位置裡面取下一個點,記錄路徑,要注意儘量靠右。
分析:一個典型的dp
#include <cstdio> #include <cmath> #include <queue> #include <map> #include <vector> #include <cstring> #include <algorithm> using namespace std; const int MAXN = 1e2+10; const int INF = 0x7fffffff; int t, m, n, dp[MAXN][MAXN]; int s[MAXN][MAXN], mp[MAXN][MAXN], icase = 1; void output(int i, int j) { if(0 == i) { return ; } if(1 == s[i][j]) { output(i-1, j-1); printf("%d ", j-1); } else if(2 == s[i][j]) { output(i-1, j); printf("%d ", j); } else if(3 == s[i][j]) { output(i-1, j+1); printf("%d ", j+1); } } int main() { scanf("%d", &t); while(t--) { scanf("%d%d", &n, &m); memset(dp, 0, sizeof(dp)); memset(mp, 0, sizeof(mp)); memset(s, 0, sizeof(s)); for(int i=1; i<=n; ++i) { for(int j=1; j<=m; ++j) { scanf("%d", &mp[i][j]); } } for(int i=1; i<=m; ++i) { dp[1][i] = mp[1][i]; } for(int i=2; i<=n; ++i) { for(int j=1; j<=m; ++j) { int mn = INF; if(j>=2 && dp[i-1][j-1] <= mn) { mn = dp[i-1][j-1]; s[i][j] = 1; } if(dp[i-1][j] <= mn) { mn = dp[i-1][j]; s[i][j] = 2; } if(j<=m-1 && dp[i-1][j+1] <= mn) { mn = dp[i-1][j+1]; s[i][j] = 3; } dp[i][j] = mn + mp[i][j]; } } int mn = INF, id = 0; for(int i=1; i<=m; ++i) { if(dp[n][i] <= mn) { mn = dp[n][i]; id = i; } } /* printf("%d\n", mn); for(int i=1; i<=n; ++i) { for(int j=1; j<=m; ++j) { printf("%d ", dp[i][j]); } printf("\n"); } */ printf("Case %d\n", icase++); output(n, id); printf("%d\n", id); } return 0; }
HDOJ 5093
分析:二分圖。
隊友寫的,沒細看,貼個隊友的程式碼,之後有空再看。
程式碼:
#include<iostream> #include<cstdio> #include<cstring> #include<algorithm> using namespace std; int match[1260]; char map[60][60]; int pic[1260][60]; int vis[1260]; int m,n; int nx=0,ny[60],nk=0,flag=0,yvis[60]; int dp(int now) { int i; for(i=0;pic[now][i]!=-1;i++) { int t=pic[now][i]; if(vis[t]==1) continue; vis[t]=1; if(match[t]==-1||dp(match[t])) { match[t]=now; return 1; } } return 0; } int main() { //freopen("D:\\in.txt","r",stdin); int t,i,j; cin>>t; while(t--) { cin>>m>>n; for(i=0;i<m;i++) scanf("%s",map[i]); memset(yvis,0,sizeof(yvis)); for(i=0;i<n;i++) ny[i]=i; nx=nk=0; flag=0; memset(pic,-1,sizeof(pic)); for(i=0;i<m;i++) { for(j=0;j<n;j++) { if(map[i][j]=='*') { yvis[j]=1; pic[nx][flag++]=ny[j]; } if(map[i][j]=='#') { if(flag) { nx++; flag=0; } if(yvis[j]) { ny[j]=n+nk; nk++; yvis[j]=0; } } } if(flag) { nx++; flag=0; } } int ans=0; memset(match,-1,sizeof(match)); for(i=0;i<=nx;i++) { memset(vis,0,sizeof(vis)); if(dp(i)) ans++; } cout<<ans<<endl; } }
HDOJ 5094
分析:BFS+狀壓(不然會MLE),wa點:一個位置可能有幾把不同的鑰匙。
#include <cstdio>
#include <cmath>
#include <queue>
#include <map>
#include <vector>
#include <cstring>
#include <algorithm>
using namespace std;
const int MAXN = 55;
int n, m, p, k, s, mk[MAXN][MAXN];
int vis[1<<11][MAXN][MAXN];
int dir[4][2] = { {-1, 0}, {1, 0}, {0, -1}, {0, 1} };
struct P
{
int x, y, time, key;
};
map<int, int> mp;
int BFS()
{
memset(vis, 0, sizeof(vis));
queue<P> que;
P s; s.x = s.y = 1;
s.key = s.time = 0;
if(mk[s.x][s.y])
{
s.key = mk[s.x][s.y];
}
vis[s.key][s.x][s.y] = 1;
que.push(s);
while(!que.empty())
{
P u = que.front();
que.pop();
if(u.x==n && u.y==m)
{
return u.time;
}
for(int i=0; i<4; ++i)
{
P v;
v.x = u.x + dir[i][0];
v.y = u.y + dir[i][1];
if(v.x<1 || v.x>n || v.y<1 || v.y>m)
{
continue;
}
int q = 51*51*51*u.x + 51*51*u.y + 51*v.x + v.y;
int tp = mp[q];
if(4e8 == tp)
{
continue;
}
if(0 == tp)
{
v.time = u.time + 1;
v.key = u.key;
if(mk[v.x][v.y] && 0==(mk[v.x][v.y]&u.key))
{
v.key += mk[v.x][v.y];
}
if(vis[v.key][v.x][v.y])
{
continue;
}
vis[v.key][v.x][v.y] = 1;
que.push(v);
}
else
{
if(u.key & (1<<tp))
{
v.time = u.time + 1;
v.key = u.key;
if(mk[v.x][v.y] && 0==(mk[v.x][v.y]&u.key))
{
v.key += mk[v.x][v.y];
}
if(vis[v.key][v.x][v.y])
{
continue;
}
vis[v.key][v.x][v.y] = 1;
que.push(v);
}
}
// printf("%d %d %d %d\n", v.x, v.y, v.time, v.key);
}
}
return -1;
}
int main()
{
while(~scanf("%d%d%d", &n, &m, &p))
{
scanf("%d", &k);
mp.clear();
memset(mk, 0, sizeof(mk));
while(k--)
{
int ux, uy, vx, vy, g, hx, hy;
scanf("%d%d%d%d%d", &ux, &uy, &vx, &vy, &g);
hx = 51*51*51*ux + 51*51*uy + 51*vx + vy;
hy = 51*51*51*vx + 51*51*vy + 51*ux + uy;
if(0 == g) g = 4e8;
mp[hx] = mp[hy] = g;
}
scanf("%d", &s);
while(s--)
{
int x, y, q;
scanf("%d%d%d", &x, &y, &q);
mk[x][y] += (1<<q);
}
printf("%d\n", BFS());
}
return 0;
}
HDOJ 5095
分析:水題,寫的時候注意處理-1,0,1就差不多了,還有首位為正,不需要+。
程式碼:
#include <cstdio>
#include <cmath>
#include <queue>
#include <map>
#include <vector>
#include <cstring>
#include <algorithm>
using namespace std;
typedef long long lint;
const int MAXN = 20;
char ch[] = {'p', 'q', 'r', 'u', 'v', 'w', 'x', 'y', 'z'};
int ia[MAXN], t;
int main()
{
scanf("%d", &t);
while(t--)
{
for(int i=0; i<10; ++i)
{
scanf("%d", ia+i);
}
int first = 1, zero = 1;
for(int i=0; i<10; ++i)
{
if(0 == ia[i])
{
continue;
}
zero = 0;
if(ia[i] < 0)
{
if(-1 == ia[i])
{
if(i < 9)
{
printf("-");
}
else
{
printf("-1");
}
}
else
{
printf("%d", ia[i]);
}
first = 0;
}
else
{
if(1 == ia[i])
{
if(!first)
{
printf("+");
}
first = 0;
if(i == 9)
{
printf("1");
}
}
else
{
if(!first)
{
printf("+");
}
first = 0;
printf("%d", ia[i]);
}
}
if(i < 9)
{
printf("%c", ch[i]);
}
}
if(zero) printf("0");
printf("\n");
}
return 0;
}
HDOJ 5098
隊友寫的,貼個程式碼,之後補。
#include<iostream>
#include<cstdio>
#include<cstring>
#include<string>
#include<map>
#include<algorithm>
using namespace std;
char info[1010][1030];
int need[1010][1010],nn[1010];
int num[1010];
int res[1010],ns; //ns為軟體數量,res表示是否要重啟
map<string,int> list;
int dfs(int now)
{
if(num[now]!=-1)
return num[now];
int ma=0,i;
for(i=0;need[now][i]!=-1;i++)
{
int t=need[now][i];
if(res[t])
ma=max(ma,dfs(t)+1);
else
ma=max(ma,dfs(t));
}
num[now]=ma;
return num[now];
}
int main()
{
//freopen("D:\\in.txt","r",stdin);
int t,i,j,count=1;
cin>>t;
getchar();
getchar();
while(t--)
{
memset(info,0,sizeof(info));
list.clear();
memset(res,0,sizeof(res));
i=0;
while(gets(info[i])) //開始資料處理
{
if(strlen(info[i])==0)
break;
j=0;
while(info[i][j]!='*'&&info[i][j]!=':')
j++;
list[string(info[i],j)]=i;
if(info[i][j]=='*')
res[i]=1;
i++;
}
ns=i;
memset(need,-1,sizeof(need));
memset(nn,0,sizeof(nn));
for(i=0;i<ns;i++)
{
int s=0;
while(info[i][s]!=' '&&s!=strlen(info[i]))
s++;
int e=s;
while(e!=strlen(info[i]))
{
s=e;
e++;
while(e!=strlen(info[i])&&info[i][e]!=' ')
e++;
need[i][nn[i]++]=list[string(info[i]+s+1,e-s-1)];
}
} //資料處理結束,need[i]表示i的依賴包,到-1結束
memset(num,-1,sizeof(num));
int ma=0;
for(i=0;i<ns;i++)
{
if(res[i])
ma=max(ma,dfs(i)+1);
else
ma=max(ma,dfs(i));
}
printf("Case %d: %d\n",count++,ma);
}
}
HDOJ 5099
分析:水題,字串比較。
程式碼:
#include <cstdio>
#include <cmath>
#include <queue>
#include <map>
#include <vector>
#include <cstring>
#include <algorithm>
using namespace std;
const int MAXN = 2e3+10;
char cha[MAXN], chb[MAXN];
int t, icase = 1;
int main()
{
scanf("%d", &t);
while(t--)
{
scanf("%s%s", cha, chb);
// puts(cha); puts(chb);
printf("Case %d: ", icase++);
if(cha[0] > chb[0])
{
printf("> ");
}
else if(cha[0] < chb[0])
{
printf("< ");
}
else
{
printf("= ");
}
if(cha[1] != chb[1])
{
cha[5] = chb[5] = '\0';
}
int ret = strcmp(cha+2, chb+2);
if(ret > 0)
{
printf(">");
}
else if(ret < 0)
{
printf("<");
}
else
{
printf("=");
}
printf("\n");
}
return 0;
}