2011年12月4日
题意:m*n的格子里放1*3的矩形,问有多少种放法。 分析:状态压缩dp,每个格子有三种状态,dp[i][j]表示到第i层状态为j的方法数。 #include <iostream> #include <memory.h> #include <stdio.h> using namespace std; #define LL long long
LL dp[31][20000],n,m,row,zt; LL num[10],pp[10];
// 状态 0----横放或者竖放的第三个格子 对下层没有影响 // 1----竖放的中间那个格子 对下一层有影响 // 2----竖放的第一个格子 对下两层有影响
void dfs(LL pos,LL status) { if(pos==n) { dp[row+1][status]+=dp[row][zt]; return; } if(num[pos]==0) // 上层为0 这层可以横放或者成2 { if(pos+2<n&&num[pos+1]==0&&num[pos+2]==0) dfs(pos+3,status); // 横放 dfs(pos+1,status+2*pp[pos]); } else if(num[pos]==1) // 上层为1 这层为0 { dfs(pos+1,status); } else // 上层为2 这层为1 { dfs(pos+1,status+pp[pos]); } }
void change() { LL now=zt,k=-1; memset(num,0,sizeof(num)); if(now==0) return; while(now) { num[++k]=now%3; now/=3; } }
int main() { LL i,nmax; pp[0]=1; for(i=1;i<=9;i++) pp[i]=pp[i-1]*3; while(scanf("%lld%lld",&n,&m)&&(m||n)) { if((m*n)%3!=0) {printf("0\n"); continue;} nmax=pp[n]; // 状态总数 memset(dp,0,sizeof(dp)); dp[0][0]=1; for(row=0;row<=m-1;row++) { for(zt=0;zt<nmax;zt++) { if(dp[row][zt]) { change(); dfs(0,0); } } } printf("%lld\n",dp[m][0]); } return 0; }
2011年12月3日
题意: ...... 分析: 二分答案,对于当前二分到的答案,验证在这个时间内是否可以完成,dp[i][j]表示到第i个人时,完成了j个A任务时最多能完成B任务的个数。然后枚举第i个人完成A任务的个数k来转移,dp[i][j]=max{dp[i-1][j-k]+第i个人完成k个A任务后还能完成B任务的个数}。 #include <iostream> #include <stdio.h> #include <memory.h> using namespace std;
int dp[110],a[110],b[110],maxx,n,m;
int judge(int now) { int i,j,k,tem; memset(dp,-1,sizeof(dp)); for(j=0;j<=m;j++) { if(j*a[1]>now) break; tem=now-j*a[1]; // 第一个人完成j个任务1后还剩的时间 tem=tem/b[1]; // 第一个人还能完成任务2的个数 dp[j]=tem; } for(i=2;i<=n;i++) { for(j=m;j>=0;j--) // 因为dp[]只用一维,所以类似完全背包 这里应该倒过来循环 { for(k=0;k<=j;k++) { if(k*a[i]>now) break; tem=now-k*a[i]; // 第i个人完成k个任务1后还剩的时间 tem=tem/b[i]; // 还能完成任务2的个数 if(dp[j-k]!=-1&&dp[j-k]+tem>dp[j]) dp[j]=dp[j-k]+tem; } } if(dp[m]>=m) return 1; } return 0; }
void solve() { int l=0,r=maxx*2*m,ans=r,mid; while(l<=r) { mid=(l+r)>>1; if(judge(mid)) { ans=mid; r=mid-1; } else l=mid+1; } printf("%d\n",ans); }
int main() { int t,i; scanf("%d",&t); while(t--) { scanf("%d%d",&n,&m); maxx=0; for(i=1;i<=n;i++) { scanf("%d%d",a+i,b+i); if(a[i]>maxx) maxx=a[i]; if(b[i]>maxx) maxx=b[i]; } solve(); } return 0; }
2011年11月30日
题意:n*m的网格,有些格子里可能有宝藏,若站在(x,y),每次只能向(x+1,y)或者(x,y+1)方向走,问最少要走几趟能将网格中的宝物收集完。 分析: 按题目的意思就是只能向右和向下走。如果将宝物的坐标按x轴来从小到大排(x轴相同的按y轴从小到大),那么就可以只考虑y坐标了 ,假设有两个位置i,j,i.x<=j.x,当i.y<=j.y时,才有可能收集完i后收集j,所以按x轴排序完后,问题就转化为用最少几个不降子序列可将y轴坐标序列全部涵盖。那就是最长(严格)递减子序列的长度了。
#include <iostream>
#include <stdio.h>
#include <memory.h>
#include <algorithm>
using namespace std;

struct node
  {
int x,y;
}a[100010];

int dp[100010],num[100010],b[100010],n,m,p;

int cmp(node p,node q)
  {
if(p.x==q.x) return p.y<q.y;
return p.x<q.x;
}

void solve() // 求最长递减子序列
  {
int i,tem,l,r,mid,ans,top;
b[1]=num[1]; top=1; dp[1]=1;
ans=0;
for(i=2;i<=p;i++)
 {
if(num[i]<b[top])
 {
b[++top]=num[i];
dp[i]=top;
}
else
 {
l=1; r=top;
while(l<=r)
 {
mid=(l+r)>>1;
if(b[mid]<=num[i])
 {
tem=mid;
r=mid-1;
}
else l=mid+1;
}
b[tem]=num[i];
dp[i]=tem;
}
if(dp[i]>ans) ans=dp[i];
}
printf("%d\n",ans);
}

int main()
  {
int i;
while(scanf("%d%d%d",&m,&n,&p)!=EOF)
 {
for(i=1;i<=p;i++)
scanf("%d%d",&a[i].x,&a[i].y);
sort(a+1,a+1+p,cmp);
for(i=1;i<=p;i++)
num[i]=a[i].y;
solve();
}
return 0;
}
2011年11月26日
摘要: 题意:有个人去一幢楼送礼物,他用两根柱状的容器装礼物,每次只能从容器的两端取出礼物送出去,上一层楼花费5的体力,下一层楼花费3的体力。求送完所有礼物耗费的最少体力。分析:不难的题目,只是目前写的人比较少而已。状态表示还是很好想出来的。dp[i1][j1][i2][j2][0]--第一根柱子到两端为i1,j1都送完,第二根到两端为i2,j2都送完,最后送的是a[i1]这个礼物所花费的最小体力。dp[... 阅读全文
2011年11月20日
题意: 将字符串压缩到最短。压缩规则见题目。 分析: 这题我就是用了最原始的方法了。一段一段来压缩。即现在要压缩[i,j]这一段时,要保证任意一段长度比j-i+1小的压缩结果都已经得出来了,也就是按长度从小到大来dp。压缩[i,j]的方法有两种,一种压缩成"数字(字符串)"的形式,另一种是压缩成[i,k][k+1,j]的形式。比较一下,哪种短就选哪种了。
#include <iostream>
#include <stdio.h>
#include <memory.h>
using namespace std;
#define inf 200000000

struct node
  {
int len;
char ss[110];
}f[110][110];

char ts[110];
int pos;

void tostring(int num)
  {
char cc;
int i;
pos=-1;
while(num)
 {
ts[++pos]=(num%10)+'0';
num/=10;
}
for(i=0;i<=pos/2;i++)
 {
cc=ts[i]; ts[i]=ts[pos-i]; ts[pos-i]=cc;
}
}

int main()
  {
int i,j,k,nlen,now,p,q,n,num;
char s[110];
while(scanf("%s",s+1)!=EOF)
 {
n=strlen(s+1);
for(i=1;i<=n;i++) // 初始化
 {
f[i][i].ss[0]=s[i];
f[i][i].ss[1]='\0';
f[i][i].len=1;
}
for(nlen=2;nlen<=n;nlen++) // 现在的长度
 {
for(i=1;i+nlen-1<=n;i++)
 {
j=i+nlen-1;
f[i][j].len=inf;
// 先看能不能压缩成"数字(字符串)"的形式
for(now=1;now<nlen;now++) // now---想折叠成的长度
 {
if(nlen%now) continue;
q=i+now; p=i;
while(q<=j)
 {
if(s[q]!=s[p]) break;
p++; q++;
if(p==i+now) p=i;
}
if(q>j) // 可以压缩成"数字(字符串)"的形式
 {
num=nlen/now;
tostring(num);
strcpy(f[i][j].ss,ts);
f[i][j].ss[++pos]='(';
for(p=0;f[i][i+now-1].ss[p];p++) f[i][j].ss[++pos]=f[i][i+now-1].ss[p];
f[i][j].ss[++pos]=')';
f[i][j].len=pos+1;
f[i][j].ss[++pos]='\0';
break;
}
}
for(k=i;k<j;k++) // [i,k][k+1,j]这种形式
 {
if(f[i][k].len+f[k+1][j].len<f[i][j].len)
 {
f[i][j].len=f[i][k].len+f[k+1][j].len;
strcpy(f[i][j].ss,f[i][k].ss);
strcat(f[i][j].ss,f[k+1][j].ss);
}
}
}
}
printf("%s\n",f[1][n].ss);
}
return 0;
}
2011年11月17日
2011年11月16日
题意:当任意两个卫星的距离小于等于25时,放置一个天线就可以同时接受到这两个卫星的信号。现在告诉n个卫星的位置,求最少需购买天线数量,同时需要保证,得到的信号值总和最大。信号值计算公式是Qx=100-|卫星的位置-天线的位置|。 分析:只要弄清楚了题意,就很容易发现这个题其实就是经典的村庄里建邮局的问题了,只不过这里要求每一段的范围在25以内。因为数据范围只有100,就没写什么优化了,直接上n^3的。 f[i][j]表示前i个卫星放j个天线所能得到的最大信号。 f[i][j]=max{f[k][j-1]+w[k+1][i]; | d[i]-d[k+1]<=25}
#include <iostream>
#include <stdio.h>
#include <memory.h>
#include <algorithm>
using namespace std;
#define eps 1e-8

int n;
double f[110][110],w[110][110],d[110];

int main()
  {
int i,j,k,tem;
while(scanf("%d",&n)!=EOF)
 {
d[0]=0.0;
for(i=1;i<=n;i++)
 {
scanf("%lf",&d[i]);
}
sort(d+1,d+n+1);
for(i=1;i<=n;i++) // 预处理出任意一段放一个卫星的所获得的最大信号值。
 {
w[i][i]=100.0;
for(j=i+1;j<=n;j++)
 {
tem=i+(j-i+1)/2;
w[i][j]=0.0;
for(k=i;k<=tem;k++)
w[i][j]+=d[tem]-d[k];
for(;k<=j;k++)
w[i][j]+=d[k]-d[tem];
w[i][j]=(j-i+1)*100.0-w[i][j];
}
}
for(i=0;i<=n;i++)
 {
for(j=0;j<=n;j++) f[i][j]=-1.0;
}
f[0][0]=0.0;
f[1][1]=100.0;
for(i=2;i<=n;i++)
 {
for(j=1;j<=i;j++)
 {
for(k=i-1;k>=j-1&&d[i]+eps<=25.0+d[k+1];k--)
 {
if(f[k][j-1]+eps<0.0) continue;
tem=i-k;
if(f[k][j-1]+w[k+1][i]>f[i][j]+eps)
f[i][j]=f[k][j-1]+w[k+1][i];
}
}
}
for(j=1;j<=n;j++)
 {
if(f[n][j]>=0) break;
}
printf("%d %.2lf\n",j,f[n][j]);
}
return 0;
}
2011年11月14日
题意:好难表达... 分析:dp了,没什么好说的,dp[now]=min{dp[i]+dp[now-i],dp[i]+dp[now/i]且now%i==0,dp[i]+dp[j]且i^j==now;} 。不过转移的时候我的方法很暴力,不知道其他优秀的方法是怎么做的。 一些很明显的值的表达式可以预处理出来。
#include <iostream>
#include <stdio.h>
#include <memory.h>
#include <cmath>
using namespace std;
#define inf 2000000000

struct node
  {
int num;
char s[100];
}a[20010];

void ini()
  {
int i,now,j,tem,cnt;
for(i=1;i<=20000;i++) a[i].num=inf;
a[1].num=1; strcpy(a[1].s,"1"); // 1,2,3,5,7预处理出来
a[2].num=1; strcpy(a[2].s,"2");
a[3].num=1; strcpy(a[3].s,"3");
a[5].num=1; strcpy(a[5].s,"5");
a[7].num=1; strcpy(a[7].s,"7");

a[4].num=2; strcpy(a[4].s,"(2^2)"); // 4也预处理
a[6].num=1; strcpy(a[6].s,"3!"); // 预处理3到7的阶乘,因为8的阶乘已经超过20000了
a[24].num=2; strcpy(a[24].s,"(2^2)!"); // 注意阶乘的表达式外面就不用括号了,我一开始加了就wa
a[120].num=1; strcpy(a[120].s,"5!");
a[720].num=1; strcpy(a[720].s,"3!!");
a[5040].num=1; strcpy(a[5040].s,"7!");
for(now=4;now<=20000;now++) // 下面就是dp了 转移的时候很暴力
 {
if(a[now].num!=inf) continue;
tem=(int)sqrt(now+0.0);
for(i=2;i<=tem;i++)
 {
if(now%i==0)
 {
j=now/i;
if(a[i].num+a[j].num<a[now].num) // *运算
 {
a[now].num=a[i].num+a[j].num;
strcpy(a[now].s,"(");
strcat(a[now].s,a[i].s);
strcat(a[now].s,"*");
strcat(a[now].s,a[j].s);
strcat(a[now].s,")");
}
cnt=now; j=0;
while(cnt%i==0&&cnt>0)
 {
++j;
cnt/=i;
}
if(cnt==1)
 {
if(a[i].num+a[j].num<a[now].num) // ^运算
 {
a[now].num=a[i].num+a[j].num;
strcpy(a[now].s,"(");
strcat(a[now].s,a[i].s);
strcat(a[now].s,"^");
strcat(a[now].s,a[j].s);
strcat(a[now].s,")");
}
}
}
}
for(i=1;i<=now/2;i++)
 {
j=now-i;
if(a[i].num+a[j].num<a[now].num) // +运算
 {
a[now].num=a[i].num+a[j].num;
strcpy(a[now].s,"(");
strcat(a[now].s,a[i].s);
strcat(a[now].s,"+");
strcat(a[now].s,a[j].s);
strcat(a[now].s,")");
}
}
}
}

int main()
  {
ini();
int n;
while(scanf("%d",&n)!=EOF)
 {
printf("%s\n",a[n].s);
}
return 0;
}
2011年11月12日
题意:给一些人的排列限制关系(比如x要排在y前面),求符合这些条件的排列总数。 分析: 这题自己没想出来,看了别人的题解。这句“我们想求一堆人的排列总数,它等于在这一堆人中 减去每一个入度为 0 的人,剩下的人的排列总数的和。”就是这题的方法了。记忆化搜索写法。
#include <iostream>
#include <memory.h>
#include <stdio.h>
#include <cstring>
using namespace std;
#define LL long long

LL dp[(1<<16)+10],g[16][16],din[16],n,m;
char name[16][20];

LL find(char s[])
  {
for(LL i=0;i<=n;i++)
 {
if(strcmp(s,name[i])==0) return i;
}
return -1;
}

LL dfs(LL now)
  {
LL i,j;
if(dp[now]>=0) return dp[now];
dp[now]=0;
for(i=0;i<n;i++)
 {
if(!din[i]&&(now&(1<<i))) // 如果i的入度为0且now这个状态含有i
 {
for(j=0;j<n;j++)
 {
if(g[i][j]) din[j]--;
}
dp[now]+=dfs(now-(1<<i)); // 递推关系
for(j=0;j<n;j++) // 恢复
 {
if(g[i][j]) din[j]++;
}
}
}
return dp[now];
}

int main()
  {
LL i,x,y,ans,nmax,j;
char s1[20],s2[20];
while(scanf("%lld",&m)!=EOF)
 {
memset(g,0,sizeof(g));
n=-1;
for(i=1;i<=m;i++)
 {
scanf("%s %s",s1,s2);
x=find(s1);
 if(x==-1) {strcpy(name[++n],s1); x=n;}
y=find(s2);
 if(y==-1) {strcpy(name[++n],s2); y=n;}
g[x][y]=1;
}
n++;
memset(din,0,sizeof(din));
for(i=0;i<n;i++)
 {
for(j=0;j<n;j++)
 {
if(g[i][j]) din[j]++;
}
}
memset(dp,-1,sizeof(dp));
for(i=0;i<n;i++) dp[(1<<i)]=1; // 只剩一个人的时,必然是1 所以先设好边界
nmax=(1<<n)-1;
ans=dfs(nmax);
printf("%lld\n",ans);
}
return 0;
}
2011年11月11日
摘要: 题意:给一个三角形,被分成了很多个三角形(具体看题目里的图),求一个最大的只包含白色三角形三角形。分析:不难但有点小恶心的题目。方法应该很多,怎么数都行了。我是用类似dp的方法的,如果上一层的[j+1,k-1]这个范围能构成一个纯白色三角形,并且这一层的[j,k]这个范围也都是白的,那么f[i][j][k]就代表了一个纯白色的大三角形。代码写得有些啰嗦,懒得简化了。
Code hig... 阅读全文
|
|
| 日 | 一 | 二 | 三 | 四 | 五 | 六 |
---|
26 | 27 | 28 | 29 | 30 | 31 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 |
|
常用链接
留言簿
随笔分类
随笔档案
搜索
最新评论

阅读排行榜
评论排行榜
|
|