2014-上海邀请赛
A Game with Pearls
传送门:hdu 5090
给定一个长度为n的数组,可以对任意一个数增加k的倍数,问能否通过调换位置,增数来使得整个数组构成一个1~n的序列
贪心,对k取模分组,因为加k取模不会变,所以首先判断对应组内的个数是否满足最终序列需要的个数,然后从小到大分别对各组内进行判断
/******************************************************
* File Name: 1001.cpp
* Author: kojimai
* Create Time: 2014年11月02日 星期日 12时47分52秒
******************************************************/
#include<cstdio>
#include<cstring>
#include<cmath>
#include<algorithm>
#include<iostream>
#include<vector>
using namespace std;
#define FFF 105
vector<int> p[FFF];
int a[FFF];
int main()
{
int keng;
scanf("%d",&keng);
while(keng--)
{
int n,k;
cin>>n>>k;
for(int i = 0;i < n;i++)
cin>>a[i];
sort(a,a+n);
for(int i = 0;i < k;i++)
{
p[i].clear();
}
for(int i = 0;i < n;i++)
{
int t = a[i]%k;
p[t].push_back(a[i]);
}
bool flag = true;
for(int i = 0;i < k && flag;i++)
{
int cnt = n / k;
if(i && i <= n % k)
cnt++;
if(cnt != p[i].size())
flag= false;
}
if(flag)
for(int i = 1;i < n&&flag;i++)
{
int t = i % k;
if(p[t][0]<=i)
{
p[t].erase(p[t].begin());
}
else
flag = false;
}
if(flag)
printf("Jerry\n");
else
printf("Tom\n");
}
return 0;
}
C Seam Carving
传送门:hdu 5092
题意比较绕,理解了题意就好做了,从上到下找一条路径,使得路径上的值最小,要求相邻行之间选到的点左右距离值不大大于1
dp类似数塔,求最小统计路径即可
P.S.上海我们队最后一小时就卡在上面了,理解了题意就是敲不出来,做重现顺利过,简直无情.....
/******************************************************
* File Name: 1003.cpp
* Author: kojimai
* Create Time: 2014年11月02日 星期日 14时25分57秒
******************************************************/
#include<cstdio>
#include<cstring>
#include<cmath>
#include<algorithm>
#include<iostream>
using namespace std;
#define FFF 105
long long a[FFF][FFF],dp[FFF][FFF];
int road[FFF][FFF];
int main()
{
int keng,Case = 1;
cin>>keng;
while(keng--)
{
int n,m;
cin>>n>>m;
for(int i = 1;i <= n;i++)
{
for(int j = 1;j <= m;j++)
{
cin>>a[i][j];
}
}
memset(dp,0,sizeof(dp));
for(int i = 1;i <= m;i++)
{
dp[n][i] = a[n][i];
road[n][i] = -1;
}
for(int i = n - 1;i >= 1;i--)
{
for(int j = m;j >= 1;j--)
{
if(j < m)
{
dp[i][j] = (dp[i+1][j+1] + a[i][j]);
road[i][j] = j+1;
if(dp[i+1][j]<dp[i+1][j+1])
{
road[i][j] = j;
dp[i][j] = dp[i+1][j]+a[i][j];
}
}
else
{
dp[i][j] = dp[i+1][j] +a[i][j];
road[i][j] = j;
}
if(j>1)
{
if(dp[i][j]>(dp[i+1][j-1]+a[i][j]))
{
road[i][j] = j-1;
dp[i][j] = dp[i+1][j-1]+a[i][j];
}
}
}
}
long long ans = dp[1][m];
int s = m;
for(int i = m - 1;i >= 1;i--)
{
if(dp[1][i] < ans)
{
ans = dp[1][i];
s = i;
}
}
printf("Case %d\n%d",Case++,s);
int cnt = 1;
while(road[cnt][s] != -1)
{
s = road[cnt++][s];
cout<<' '<<s;
}
cout<<endl;
}
return 0;
}
D Battle ships
传送门:hdu 5093
给定一张图,在*位置可以放点,O表示不可放点但点之间可以通过该点相连,#表示可以隔断点问最多放多少个点,使得两两之间不可达
二分图匹配,对每个点进行拆点,分行与列对点编号,同一行或同一列中,中间有#则在行或者列上,该点拆成多个点,这样拆完点之后得到一张二分图进行一次二分匹配即可
/******************************************************
* File Name: 1004.cpp
* Author: kojimai
* Create Time: 2014年11月02日 星期日 13时12分13秒
******************************************************/
#include<cstdio>
#include<cstring>
#include<cmath>
#include<algorithm>
#include<iostream>
using namespace std;
#define FFF 55
char s[FFF][FFF];
int hang[FFF][FFF],lie[FFF][FFF];
#define FF 1300
int match[FF],cntx,cnty;
bool mm[FF][FF],vis[FF];
bool dfs(int now)
{
for(int i = 0;i < cnty;i++)
{
if(mm[now][i]&&!vis[i])
{
vis[i] = true;
if(match[i] == -1 || dfs(match[i]))
{
match[i] = now;
return true;
}
}
}
return false;
}
void printhang()
{
for(int i = 0;i < 4;i++)
{
for(int j = 0;j < 4;j++)
cout<<hang[i][j]<<' ';
cout<<endl;
}
}
void printlie()
{
for(int i = 0;i < 4;i++)
{
for(int j = 0;j < 4;j++)
cout<<lie[i][j]<<' ';
cout<<endl;
}
}
int main()
{
int keng;
cin>>keng;
while(keng--)
{
int n,m;
scanf("%d%d",&n,&m);
for(int i = 0;i < n;i++)
cin>>s[i];
cntx = cnty = 0;
bool flag = false;
memset(hang,-1,sizeof(hang));
memset(lie,-1,sizeof(lie));
for(int i = 0;i < n;i++)
{
for(int j = 0;j < m;j++)
{
if(s[i][j] == '*')
{
hang[i][j] = cntx;
flag = true;
}
else if(s[i][j] == '#')
{
if(flag == true)
{
flag = false;
cntx++;
}
}
}
if(flag)
{
flag = false;
cntx++;
}
}
//在行上拆点
//printhang();
flag = false;
for(int i = 0;i < m;i++)
{
for(int j = 0;j < n;j++)
{
if(s[j][i] == '*')
{
lie[j][i] = cnty;
flag = true;
}
else if(s[j][i] == '#')
{
if(flag)
{
flag = false;
cnty++;
}
}
}
if(flag)
{
flag = false;
cnty++;
}
}
//在列上拆点
//printlie();
//cout<<" cntx = "<<cntx<<" cnty = "<<cnty<<endl;
memset(mm,false,sizeof(mm));
for(int i = 0;i < n;i++)
{
for(int j = 0;j < m;j++)
{
if(s[i][j] == '*')
{
mm[hang[i][j]][lie[i][j]] = true;
}
}
}
//for(int i = 0;i < cntx;i++)
//{
// for(int j = 0;j < cnty;j++)
// cout<<mm[i][j]<<' ';
// cout<<endl;
//}
memset(match,-1,sizeof(match));
int ans = 0;
for(int i = 0;i < cntx;i++)
{
memset(vis,false,sizeof(vis));
if(dfs(i))
ans++;
}
//答案即为最大匹配数
cout<<ans<<endl;
}
return 0;
}
F Linearization of the kernel functions in SVM
传送门:hdu 5095
签到题,注意各种边界条件处理即可
/******************************************************
* File Name: 1006.cpp
* Author: kojimai
* Create Time: 2014年11月02日 星期日 13时39分25秒
******************************************************/
#include<cstdio>
#include<cstring>
#include<cmath>
#include<algorithm>
#include<iostream>
using namespace std;
bool first;
void printnum(int x)
{
if(first)
{
first = false;
if(x>0)
{
if(x == 1)
return;
else
cout<<x;
}
else
{
if(x == -1)
cout<<'-';
else
cout<<x;
}
}
else
{
if(x>0)
{
if(x == 1)
cout<<'+';
else
cout<<'+'<<x;
}
else
{
if(x == -1)
cout<<'-';
else
cout<<x;
}
}
return;
}
void printp(int x)
{
if(x == 0)
return;
printnum(x);
cout<<'p';
}
void printq(int x)
{
if(x == 0)
return;
printnum(x);
cout<<'q';
}
void printr(int x)
{
if(x == 0)
return;
printnum(x);
cout<<'r';
}
void printu(int x)
{
if(x == 0)
return;
printnum(x);
cout<<'u';
}
void printv(int x)
{
if(x == 0)
return;
printnum(x);
cout<<'v';
}
void printw(int x)
{
if(x == 0)
return;
printnum(x);
cout<<'w';
}
void printx(int x)
{
if(x == 0)return;
printnum(x);
cout<<'x';
}
void printy(int x)
{
if(x == 0)return;
printnum(x);
cout<<'y';
}
void printz(int x)
{
if(x == 0)return;
printnum(x);
cout<<'z';
}
int main()
{
int keng;
cin>>keng;
while(keng--)
{
int p,q,r,u,v,w,x,y,z,j;
cin>>p>>q>>r>>u>>v>>w>>x>>y>>z>>j;
first = true;
printp(p);
printq(q);
printr(r);
printu(u);
printv(v);
printw(w);
printx(x);
printy(y);
printz(z);
if(j)
{
if(!first&&j>0)
cout<<'+'<<j;
else
cout<<j;
first = false;
}
if(first)
cout<<0<<endl;
cout<<endl;
}
return 0;
}
J Comparison of Android versions
传送门:hdu 5099
水题,比较大小就好,一个注意点,分支相同时,在时间比较上才需要考虑最后一个字母
/******************************************************
* File Name: 1010.cpp
* Author: kojimai
* Create Time: 2014年11月02日 星期日 14时09分47秒
******************************************************/
#include<cstdio>
#include<cstring>
#include<cmath>
#include<algorithm>
#include<iostream>
using namespace std;
char s1[10],s2[10];
int main()
{
int keng,Case =1;
cin>>keng;
while(keng--)
{
int num1,num2;
cin>>s1>>s2;
if(s1[0] == s2[0])
{
num1 =0 ;
}
else if(s1[0] > s2[0])
num1 = 1;
else
num1 = -1;
if(s1[2] < s2[2])
num2 = -1;
else if(s1[2] > s2[2])
num2 = 1;
else
{
int tmp1 = (s1[3]-'0')*10+s1[4]-'0';
int tmp2 = (s2[3]-'0')*10+s2[4]-'0';
if(tmp1>tmp2)
num2 = 1;
else if(tmp1<tmp2)
num2 = -1;
else
{
num2 = 0;
}
}
if(num2 == 0 && s1[1] == s2[1])
{
if(s1[5]>s2[5])
{
num2 = 1;
}
else if(s1[5]<s2[5])
num2 = -1;
}
printf("Case %d: ",Case++);
if(num1==1)
cout<<'>';
else if(num1 == 0)
cout<<'=';
else
cout<<'<';
cout<<' ';
if(num2==1)
cout<<'>';
else if(num2==-1)
cout<<'<';
else
cout<<'=';
cout<<endl;
}
return 0;
}