hdu 4597 - Play Game
题意:
有两副牌,每副都有N张牌,每次只能从最上面或者最下面拿牌,每拿到一张牌,就加上这张牌的分数,问Alice先手的话最后她能得到的最大值
思路:
区间dp
dp[l][r][ll][rr] 表示当前(l,r)(ll,rr)这个子牌堆下,此人能够得到的最大分数,那么状态转移方程应该是:
dp[当前区间] = 当前区间的总分值 - 上一状态另一个人能够拿到的分数的最小值
而"上一状态"无非就是四种方式拿牌的情况
代码:
#pragma comment(linker, "/STACK:102400000,102400000")
#include "iostream"
#include "cstring"
#include "algorithm"
#include "cmath"
#include "cstdio"
#include "sstream"
#include "queue"
#include "vector"
#include "string"
#include "stack"
#include "cstdlib"
#include "deque"
#include "fstream"
#include "map"
#define eps 1e-14
using namespace std;
typedef long long LL;
const int MAXN = 1000000+100;
const int INF = 0x6fffffff;
const int inf = 522133279;
const long long LLinf = 1e30;
int sum[2][30];
int dp[30][30][30][30];
int zouqi(int shangl , int shangr , int xial , int xiar)
{
if(shangl >shangr && xial >xiar)
return 0;
if(dp[shangl][shangr][xial][xiar])
return dp[shangl][shangr][xial][xiar];
int cur = sum[0][shangr] - sum[0][shangl-1] + sum[1][xiar] - sum[1][xial-1];
int v=0;
if(shangl <= shangr)
{
v = max(max(v,cur - zouqi(shangl+1,shangr,xial,xiar)),
cur - zouqi(shangl , shangr-1 , xial , xiar));
}
if(xial <= xiar)
{
v = max(max(v,cur - zouqi(shangl,shangr,xial+1,xiar)),
cur - zouqi(shangl , shangr , xial , xiar-1));
}
return dp[shangl][shangr][xial][xiar] = v;
}
int main()
{
int t;
scanf("%d" , &t);
while(t--)
{
memset(dp,0,sizeof(dp));
memset(sum,0,sizeof(sum));
int n;
scanf("%d" , &n);
for(int i = 0 ; i < 2 ; i++)
for(int j = 1 ; j <= n; j++)
{
scanf("%d" , &sum[i][j]);
sum[i][j] += sum[i][j-1];
}
zouqi(1,n,1,n);
printf("%d\n" , dp[1][n][1][n]);
}
return 0;
}
hdu 4497 - GCD and LCM
对于某一质数Pi,设总指数为p,将三个数P1^a,P1^b,P1^c放入x,y,z中,由于三个指数互质,所以其中一定会出现一个以上的0(否则x,y,z就不互质了) ,并且要使n为LCM的话,max(a,b,c) = p (否则能找到更小的LCM)
考虑排列的话,分如下情况:
(1) 一个0,但有两个数相同,3(两个0)+3(两个p) = 6种情况
(2)一个0且另外两数不同,6*(p-1) 种情况
故最后对于每个质数,都有6p种安排法,则最后答案连乘就可以得到了
代码:
#pragma comment(linker, "/STACK:102400000,102400000")
#include "iostream"
#include "cstring"
#include "algorithm"
#include "cmath"
#include "cstdio"
#include "sstream"
#include "queue"
#include "vector"
#include "string"
#include "stack"
#include "cstdlib"
#include "deque"
#include "fstream"
#include "map"
#define eps 1e-14
using namespace std;
typedef long long LL;
const int MAXN = 1000000+100;
const int INF = 0x6fffffff;
const int inf = 522133279;
const long long LLinf = 1e30;
int p[1000];
int main()
{
int t;
cin >> t;
while(t--)
{
LL m,n;
cin >> m >> n;
memset(p,0,sizeof(p));
if(n%m)
{
cout << 0 << endl;
continue;
}
n/=m;
int cnt=0;
LL r = (LL)sqrt(1.0*n)+1;
for(LL i = 2 ; i < r ; i++)
{
if(n%i == 0)
{
while(n%i == 0)
{
p[cnt]++;
n/=i;
}
cnt++;
}
}
if(n != 1)
p[cnt++]=1;
LL ans=1;
for(int i = 0 ; p[i] ; i++)
ans *= 6*p[i];
cout << ans <<endl;
}
return 0;
}
hdu 4493 - Tutor
给十二个小数求平均值,要求不能输出后导0,小数部分最多2位
思路:
这么水的题训练的时候纠结了好久,总之一句话:sprintf和sscanf是个好东西
代码:
#pragma comment(linker, "/STACK:102400000,102400000")
#include "iostream"
#include "cstring"
#include "algorithm"
#include "cmath"
#include "cstdio"
#include "sstream"
#include "queue"
#include "vector"
#include "string"
#include "stack"
#include "cstdlib"
#include "deque"
#include "fstream"
#include "map"
#define eps 1e-14
using namespace std;
typedef long long LL;
const int MAXN = 1000000+100;
const int INF = 0x6fffffff;
const int inf = 522133279;
const long long LLinf = 1e30;
int main()
{
int t;
scanf("%d" , &t);
while(t--)
{
double tmp;
double res=0;
for(int i = 0 ; i < 12 ; i++)
{
scanf("%lf" , &tmp);
res+=tmp;
}
res /= 12;
char a[20];
sprintf(a,"%.2lf",res);
int len = strlen(a);
if(a[len-1] == '0' && a[len-2] == '0')
a[len-3] = '\0';
else if(a[len-1] == '0')
a[len-1] = '\0';
printf("$%s\n" , a);
}
return 0;
}
hdu 4496 - D-City
//#pragma comment(linker, "/STACK:102400000,102400000")
#include "iostream"
#include "cstring"
#include "string"
#include "cmath"
#include "queue"
#include "cstdio"
#include "algorithm"
#include "cctype"
#include "vector"
#include "map"
#include "stack"
using namespace std;
typedef long long LL;
const int INF = 0x6fffffff;
const int inf = 522133279;
const LL llinf = 1e30;
const double eps = 1e-10;
int n,m;
int f[10010];
int e[100010][2];
stack<int> lis;
int find(int x)
{
return x == f[x] ? x : f[x] = find(f[x]);
}
int merger(int x,int y)
{
x = find(x);
y = find(y);
if(x != y)
{
f[x]=y;
return 1;
}
return 0;
}
int main()
{
//freopen("input.txt" , "r" , stdin);
//freopen("out.txt","w",stdout);
while(~scanf("%d%d" , &n,&m))
{
while(!lis.empty())
lis.pop();
for(int i = 0 ; i < m ; i++)
scanf("%d%d" , &e[i][0] , &e[i][1]);
for(int i= 0 ; i <= n ; i++)
f[i]=i;
int cnt=n;
lis.push(cnt);
for(int i = m-1 ; i >= 0 ; i--)
{
cnt -= merger(e[i][0] , e[i][1]);
lis.push(cnt);
}
lis.pop();
while(!lis.empty())
{
printf("%d\n" , lis.top());
lis.pop();
}
}
return 0;
}
hdu 4499 - Cannon
题意:
就是说一个棋盘里最多能放几个中国象棋的炮使得他们不能在一步之内吃到对方
这个棋盘开始有几格是被其他棋子占了的
思路:
棋盘很小,所以爆搜
选择dfs,从上到下,从左往右搜,优先从左往右搜,这样的话只要判断上和左两个方向就可以知道当前位置能不能放了
代码:
//#pragma comment(linker, "/STACK:102400000,102400000")
#include "iostream"
#include "cstring"
#include "string"
#include "cmath"
#include "queue"
#include "cstdio"
#include "algorithm"
#include "cctype"
#include "vector"
#include "map"
#include "stack"
using namespace std;
typedef long long LL;
const int INF = 0x6fffffff;
const int inf = 522133279;
const LL llinf = 1e30;
const double eps = 1e-10;
int n,m,q;
int g[10][10];
int maxc;
int ok(int x , int y)
{
int yes=1;
for(int i = x-1 ; i >= 0 ; i--) //上方
if(g[i][y])
{
int cnt=0;
for(int j = i-1 ; j >= 0 ; j--)
{
if(g[j][y] == 1)
cnt++;
if(g[j][y] == 2 && cnt == 0)
{
yes=0;
break;
}
}
break;
}
if(!yes)
return 0;
for(int i = y-1 ; i >= 0 ; i--) //左方
if(g[x][i])
{
int cnt=0;
for(int j = i-1 ; j >= 0 ; j--)
{
if(g[x][j] == 1)
cnt++;
if(g[x][j] == 2 && cnt == 0)
{
yes=0;
break;
}
}
break;
}
return yes;
}
void dfs(int x , int y , int cnt)
{
if(x >= n)
{
maxc = max(maxc , cnt);
return;
}
if(y >= m)
{
dfs(x+1,0,cnt);
return;
}
if(g[x][y])
{
dfs(x,y+1,cnt);
return;
}
if(ok(x,y))
{
g[x][y]=2;
dfs(x,y+1,cnt+1);
g[x][y]=0;
}
dfs(x,y+1,cnt); //不管能不能放,最后还是要走下去的,刚开始把这句放在else里就错了
}
int main()
{
//freopen("input.txt" , "r" , stdin);
//freopen("out.txt","w",stdout);
while(~scanf("%d%d%d" , &n,&m,&q))
{
maxc = -1;
memset(g,0,sizeof(g));
for(int i = 0 ; i < q ; i++)
{
int a,b;
scanf("%d%d" , &a,&b);
g[a][b]=1;
}
dfs(0,0,0);
printf("%d\n",maxc);
}
return 0;
}