Problem A: gift
Time Limit: 1000 ms Memory Limit: 128 MB
Input
输入的第一行为一个整数t。 接下来t行,每行包含九个自然数a,b,c,d,e,f,g,h,i
Output
Sample Input
1 21 30 0 0 0 0 0 0 2147483647
Sample Output
3223322629
HINT
40% t<=1000
100% t<=100000 a,b,c,d,e,f,g,h<=60 i<=9223372036854775808
看到数据范围后,觉得这根本不是礼物好吗?
刚开始觉得要用高精度,后来发现用unsigned long long再加上极限数据的特判就行了。
AC code:
#include<iostream>
#include<cstring>
#include<cstdio>
using namespace std;
unsigned long long a[10],ans,mi[65],inf=9223372036854775808;
int t,s;
int x[100],y[100];
unsigned long long mix(unsigned long long n){//快速幂
if(mi[n]!=0)return mi[n];
if(n%2==0)return mi[n]=mix(n/2)*mix(n/2);
else return mi[n]=mix(n/2)*mix(n/2+1);
}
int main(){
scanf("%d",&t);
mi[0]=1;
mi[1]=2;
while(t--){
ans=0;
for(int i=1;i<=9;i++){
scanf("%llu",&a[i]);
if(i!=9)s+=a[i];
};
if(s==60*8&&a[9]==inf){//特判
cout<<"18446744073709551616"<<endl;
continue;
}
for(int i=1;i<=8;i++){
ans+=mix(a[i]);
}
ans+=a[9];
printf("%llu\n",ans);
}
return 0;
}//测试数据
/*
1
60 60 60 60 60 60 60 60 9223372036854775808
*/
/*
1
60 58 59 59 58 60 58 58 1993031419930314
*/
/*
2
60 60 60 60 60 60 60 60 9223372036854775808
60 58 59 59 58 60 58 58 1993031419930314
*/
代码如果不太好看不要喷我哈~
Problem B: 新数独
Time Limit: 1000 ms Memory Limit: 128 MBDescription
Input
Output
Sample Input
< > > < > < v v ^ ^ v v ^ ^ ^ < < > < > < ^ ^ ^ v ^ ^ ^ v v < < < < > > > < > > > > v ^ ^ ^ ^ v v v ^ > > > > < > v v ^ v ^ v ^ v ^ > < < > > > < < < < > < v ^ v v v v ^ ^ v < > > < < > ^ v v v ^ v ^ v v < > < > < >
Sample Output
4 9 1 7 3 6 5 2 8 2 3 7 8 1 5 6 4 9 5 6 8 2 4 9 7 3 1 9 1 3 6 5 4 8 7 2 8 5 4 9 7 2 1 6 3 7 2 6 3 8 1 9 5 4 3 4 9 5 6 8 2 1 7 1 8 5 4 2 7 3 9 6 6 7 2 1 9 3 4 8 5
哎,这题真的恶心了我好久,特别是输入。
其实记录好每行、每列、每个九宫格里数的关系,每个格子和它的上、左两个数之间的大小关系直接爆搜就好。
AC code:
#include<iostream>
#include<cstdio>
#include<cstring>
using namespace std;
int l[10][10],up[10][10],n[15][10],m[15][10],g[10][10];
int a[10][10];
void print(){//输出
for(int i=1;i<=9;i++){
for(int j=1;j<=9;j++){
cout<<a[i][j]<<" ";
}
cout<<endl;
}
}
int cmp(int x,int y){
return x>y?-1:1;
}
bool check(int x,int y,int n){
if(cmp(n,a[x-1][y])!=up[x][y]&&up[x][y]!=0)return 0;//比较上下
if(cmp(n,a[x][y-1])!=l[x][y]&&l[x][y]!=0)return 0;//比较左右
return 1;
}
void dfs(int x,int y){
for(int i=1;i<=9;i++){//试数
if(!n[x][i]&&!m[y][i]&&!g[(x-1)/3*3+(y-1)/3+1][i]&&check(x,y,i)){//n数组记录每行,m数组记录每列,g数组记录每个九宫格
n[x][i]=g[(x-1)/3*3+(y-1)/3+1][i]=m[y][i]=1;
a[x][y]=i;//记录
if(x==9&&y==9){//只要一个解
print();
exit(0);//赶紧溜了
}
else (y==9?dfs(x+1,1):dfs(x,y+1));
n[x][i]=g[(x-1)/3*3+(y-1)/3+1][i]=m[y][i]=0;
a[x][y]=0;
}
}
}
int main(){
char ch[2];
for(int i=1;i<=9;i++){//恶心的输入
for(int j=1;j<=9;j++){//l数组记录左右的大小关系,up数组记录上下的大小关系
if(j%3!=0){
scanf("%s",ch);
if(ch[0]=='>')l[i][j+1]=1;
else l[i][j+1]=-1;
}
}
if(i%3!=0){
for(int j=1;j<=9;j++){
scanf("%s",ch);
if(ch[0]=='v')up[i+1][j]=1;
else up[i+1][j]=-1;
}
}
}
dfs(1,1);//爆搜开始了~
return 0;
}
/*
< > > < > <
v v ^ ^ v v ^ ^ ^
< < > < > <
^ ^ ^ v ^ ^ ^ v v
< < < < > >
> < > > > >
v ^ ^ ^ ^ v v v ^
> > > > < >
v v ^ v ^ v ^ v ^
> < < > > >
< < < < > <
v ^ v v v v ^ ^ v
< > > < < >
^ v v v ^ v ^ v v
< > < > < >
*/
Problem C: 城市交通
Time Limit: 1000 ms Memory Limit: 128 MB
Description
由于牛奶市场的需求,奶牛必须前往城市,但是唯一可用的交通工具是出租车.教会奶牛如何在城市里打的.
给出一个城市地图,东西街区E(1≤E≤40),南北街区N(1≤N≤30).制作一个开车指南给出租车司机,告诉他如何从起点(用S表示)到终点(用E表示).每一个条目用空格分成两部分,第一个部分是方向(N,E,S,W之一),第二个是一个整数,表示要沿着这个方向开几个十字路口.如果存在多条路线,你应该给出最短的.数据保证,最短的路径存在且唯一.地图中“+”表示十字路口,道路用“I”和“一”表示.建筑和其他设施用“.”表示.下面是一张地图:
出租车可以沿着东,北,西,北,东开两个十字路口,以此类推.具体将由样例给出。
Input
第1行:两个用空格隔开的整数N和E.
第2到2N行:每行有2E-I个字符,表示地图.
Output
Sample Input
3 6
+-+-+.+-+-+
|...|.....|
+-+.+-+-+-+
..|.......|
S-+-+-+.E-+
Sample Output
E 1
N 1
W 1
N 1
E 2
S 1
E 3
S 1
W 1
有人说这题用广搜好,我觉得吧......用SPFA更好些
把每个 + 看成一个点,每个 | 或 - 看成一条边,然后跑一遍最短路即可。
(代码有点长,思路很清晰的,耐心看一看哈,看不下去的别喷我)
AC code:
#include<iostream>
#include<cstring>
#include<queue>
#include<cstdio>
using namespace std;
int n,m,head[4800],len,dis[4800],lu[4800],s,t;
char ans[4805];
bool vis[4800];
struct edge{//边结构体
int v,next;//v表示指向点,next表示与这条边同一出发点的另一条边
edge(){}
edge(int _v,int _next){//构造函数
v=_v;
next=_next;
}
}e[9600];
char map[100][100];
void init(){//初始化
len=0;
memset(head,-1,sizeof(head));
}
void spfa(int u){//啥,你不会spfa?那我也无能为力了
memset(dis,0x3f,sizeof(dis));
dis[u]=0;
lu[u]=s;
queue<int> q;
q.push(u);
while(!q.empty()){
u=q.front();
q.pop();
vis[u]=0;
for(int i=head[u];~i;i=e[i].next){
int v=e[i].v;
if(dis[v]>dis[u]+1){
dis[v]=dis[u]+1;
lu[v]=u;
if(!vis[v]){
q.push(v);
vis[v]=1;
}
}
}
}
}
int get(int x,int y){//get函数计算点的编号
return (x-1)*m+y;
}
void add(int u,int v){//插入边
e[len]=edge(v,head[u]);
head[u]=len++;
}
int tot;
void find(int x){
if(x==s)return;
find(lu[x]);
tot++;
if(x==lu[x]+2)ans[tot]='E';
if(x==lu[x]-2)ans[tot]='W';
if(x==lu[x]+m*2)ans[tot]='S';
if(x==lu[x]-m*2)ans[tot]='N';
}
int main(){
init();
cin>>n>>m;
n=n*2-1;
m=m*2-1;
char ch;
ch=getchar();
for(int i=1;i<=n;i++){//输入,把S和E看成+
for(int j=1;j<=m;j++){
map[i][j]=getchar();
if(map[i][j]=='S'){
s=get(i,j);
map[i][j]='+';
}
if(map[i][j]=='E'){
t=get(i,j);
map[i][j]='+';
}
}
ch=getchar();
}
for(int i=1;i<=n;i++){
for(int j=1;j<=m;j++){
if(i>=3){//插入边
if(map[i-2][j]=='+'&&map[i-1][j]!='.'){
add(get(i-2,j),get(i,j));
add(get(i,j),get(i-2,j));
}
}
if(j>=3){//还是插入边
if(map[i][j-2]=='+'&&map[i][j-1]!='.'){
add(get(i,j-2),get(i,j));
add(get(i,j),get(i,j-2));
}
}
}
}
spfa(s);//不多说,直接spfa
find(t);//找答案
for(int i=1;i<=tot;i++){//输出
int p=0;
while(ans[i]==ans[i+1]){
p++;
i++;
}
printf("%c %d\n",ans[i],p+1);
}
return 0;
}//数据看上面↑↑↑
Problem D: 雷涛的小猫
Time Limit: 2000 ms Memory Limit: 128 MB
Description
Input

Output

Sample Input
3 10 2
3 1 4 10
6 3 5 9 7 8 9
5 4 5 3 6 9
Sample Output
8
HINT
直接动规,不多说。状态转移方程:@#¥%……% 我太懒了不想写 聪明人才看得懂。(老铁没毛病)
AC code:
#include<iostream>
#include<cstdio>
using namespace std;
int n,h,d,a[2005][2005],f[2005][2005];
int main(){
scanf("%d%d%d",&n,&h,&d);
int x,y;
for(int i=1;i<=n;i++){//倒序存储
scanf("%d",&x);
for(int j=1;j<=x;j++){
scanf("%d",&y);
a[i][h-y+1]++;
}
}
for(int i=1;i<=n;i++){
int sum=0;
for(int j=1;j<=d;j++){//在h-d+1之上的位置只能从树顶跳下来
sum+=a[i][j];
f[i][j]=sum;
}
}
for(int i=d+1;i<=h;i++){//注意一下i和j与上面表示的是不同的
int maxn=0;
for(int j=1;j<=n;j++)maxn=max(maxn,f[j][i-d]);
for(int j=1;j<=n;j++)f[j][i]=max(maxn,f[j][i-1])+a[j][i];
}
int ans=0;
for(int i=1;i<=n;i++)ans=max(ans,f[i][h]);
cout<<ans;
return 0;
}
呼,终于写完了,第一次写博客,大家多多支持下哈!